Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
38de2aa494
commit
fa6c2426a5
|
@ -1 +1 @@
|
|||
3aa577d5e9ad572a22966775126076ec4dce2bfb
|
||||
d5024702496569b6de051046e5e295c44de94be5
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
GlSprintf,
|
||||
} from '@gitlab/ui';
|
||||
import { s__, __ } from '~/locale';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import Tracking from '~/tracking';
|
||||
import {
|
||||
trackAlertIntegrationsViewsOptions,
|
||||
|
@ -54,7 +53,6 @@ export default {
|
|||
GlTooltip: GlTooltipDirective,
|
||||
GlModal: GlModalDirective,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
props: {
|
||||
integrations: {
|
||||
type: Array,
|
||||
|
@ -170,7 +168,7 @@ export default {
|
|||
</template>
|
||||
|
||||
<template #cell(actions)="{ item }">
|
||||
<gl-button-group v-if="glFeatures.httpIntegrationsList" class="gl-ml-3">
|
||||
<gl-button-group class="gl-ml-3">
|
||||
<gl-button icon="pencil" @click="$emit('edit-integration', { id: item.id })" />
|
||||
<gl-button
|
||||
v-gl-modal.deleteIntegration
|
||||
|
|
|
@ -1,494 +0,0 @@
|
|||
<script>
|
||||
import {
|
||||
GlAlert,
|
||||
GlButton,
|
||||
GlForm,
|
||||
GlFormGroup,
|
||||
GlFormInput,
|
||||
GlFormInputGroup,
|
||||
GlFormTextarea,
|
||||
GlLink,
|
||||
GlModal,
|
||||
GlModalDirective,
|
||||
GlSprintf,
|
||||
GlFormSelect,
|
||||
} from '@gitlab/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import { doesHashExistInUrl } from '~/lib/utils/url_utility';
|
||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
import service from '../services';
|
||||
import {
|
||||
i18n,
|
||||
integrationTypes,
|
||||
JSON_VALIDATE_DELAY,
|
||||
targetPrometheusUrlPlaceholder,
|
||||
targetOpsgenieUrlPlaceholder,
|
||||
sectionHash,
|
||||
} from '../constants';
|
||||
import createFlash, { FLASH_TYPES } from '~/flash';
|
||||
|
||||
export default {
|
||||
i18n,
|
||||
csrf,
|
||||
targetOpsgenieUrlPlaceholder,
|
||||
targetPrometheusUrlPlaceholder,
|
||||
components: {
|
||||
GlAlert,
|
||||
GlButton,
|
||||
GlForm,
|
||||
GlFormGroup,
|
||||
GlFormInput,
|
||||
GlFormInputGroup,
|
||||
GlFormSelect,
|
||||
GlFormTextarea,
|
||||
GlLink,
|
||||
GlModal,
|
||||
GlSprintf,
|
||||
ClipboardButton,
|
||||
ToggleButton,
|
||||
},
|
||||
directives: {
|
||||
'gl-modal': GlModalDirective,
|
||||
},
|
||||
inject: ['prometheus', 'generic', 'opsgenie'],
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
selectedIntegration: integrationTypes[0].value,
|
||||
options: integrationTypes,
|
||||
active: false,
|
||||
token: '',
|
||||
targetUrl: '',
|
||||
feedback: {
|
||||
variant: 'danger',
|
||||
feedbackMessage: '',
|
||||
isFeedbackDismissed: false,
|
||||
},
|
||||
testAlert: {
|
||||
json: null,
|
||||
error: null,
|
||||
},
|
||||
canSaveForm: false,
|
||||
serverError: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
sections() {
|
||||
return [
|
||||
{
|
||||
text: this.$options.i18n.usageSection,
|
||||
url: this.generic.alertsUsageUrl,
|
||||
},
|
||||
{
|
||||
text: this.$options.i18n.setupSection,
|
||||
url: this.generic.alertsSetupUrl,
|
||||
},
|
||||
];
|
||||
},
|
||||
isPrometheus() {
|
||||
return this.selectedIntegration === 'PROMETHEUS';
|
||||
},
|
||||
isOpsgenie() {
|
||||
return this.selectedIntegration === 'OPSGENIE';
|
||||
},
|
||||
selectedIntegrationType() {
|
||||
switch (this.selectedIntegration) {
|
||||
case 'HTTP': {
|
||||
return {
|
||||
url: this.generic.url,
|
||||
token: this.generic.token,
|
||||
active: this.generic.active,
|
||||
resetKey: this.resetKey.bind(this),
|
||||
};
|
||||
}
|
||||
case 'PROMETHEUS': {
|
||||
return {
|
||||
url: this.prometheus.url,
|
||||
token: this.prometheus.token,
|
||||
active: this.prometheus.active,
|
||||
resetKey: this.resetKey.bind(this, 'PROMETHEUS'),
|
||||
targetUrl: this.prometheus.prometheusApiUrl,
|
||||
};
|
||||
}
|
||||
case 'OPSGENIE': {
|
||||
return {
|
||||
targetUrl: this.opsgenie.opsgenieMvcTargetUrl,
|
||||
active: this.opsgenie.active,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
showFeedbackMsg() {
|
||||
return this.feedback.feedbackMessage && !this.isFeedbackDismissed;
|
||||
},
|
||||
showAlertSave() {
|
||||
return (
|
||||
this.feedback.feedbackMessage === this.$options.i18n.testAlertFailed &&
|
||||
!this.isFeedbackDismissed
|
||||
);
|
||||
},
|
||||
prometheusInfo() {
|
||||
return this.isPrometheus ? this.$options.i18n.prometheusInfo : '';
|
||||
},
|
||||
jsonIsValid() {
|
||||
return this.testAlert.error === null;
|
||||
},
|
||||
canTestAlert() {
|
||||
return this.active && this.testAlert.json !== null;
|
||||
},
|
||||
canSaveConfig() {
|
||||
return !this.loading && this.canSaveForm;
|
||||
},
|
||||
baseUrlPlaceholder() {
|
||||
return this.isOpsgenie
|
||||
? this.$options.targetOpsgenieUrlPlaceholder
|
||||
: this.$options.targetPrometheusUrlPlaceholder;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'testAlert.json': debounce(function debouncedJsonValidate() {
|
||||
this.validateJson();
|
||||
}, JSON_VALIDATE_DELAY),
|
||||
targetUrl(oldVal, newVal) {
|
||||
if (newVal && oldVal !== this.selectedIntegrationType.targetUrl) {
|
||||
this.canSaveForm = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.prometheus.active || this.generic.active || !this.opsgenie.opsgenieMvcIsAvailable) {
|
||||
this.removeOpsGenieOption();
|
||||
} else if (this.opsgenie.active) {
|
||||
this.setOpsgenieAsDefault();
|
||||
}
|
||||
this.active = this.selectedIntegrationType.active;
|
||||
this.token = this.selectedIntegrationType.token ?? '';
|
||||
},
|
||||
methods: {
|
||||
createUserErrorMessage(errors = {}) {
|
||||
const error = Object.entries(errors)?.[0];
|
||||
if (error) {
|
||||
const [field, [msg]] = error;
|
||||
this.serverError = `${field} ${msg}`;
|
||||
}
|
||||
},
|
||||
setOpsgenieAsDefault() {
|
||||
this.options = this.options.map(el => {
|
||||
if (el.value !== 'OPSGENIE') {
|
||||
return { ...el, disabled: true };
|
||||
}
|
||||
return { ...el, disabled: false };
|
||||
});
|
||||
this.selectedIntegration = this.options.find(({ value }) => value === 'OPSGENIE').value;
|
||||
if (this.targetUrl === null) {
|
||||
this.targetUrl = this.selectedIntegrationType.targetUrl;
|
||||
}
|
||||
},
|
||||
removeOpsGenieOption() {
|
||||
this.options = this.options.map(el => {
|
||||
if (el.value !== 'OPSGENIE') {
|
||||
return { ...el, disabled: false };
|
||||
}
|
||||
return { ...el, disabled: true };
|
||||
});
|
||||
},
|
||||
resetFormValues() {
|
||||
this.testAlert.json = null;
|
||||
this.targetUrl = this.selectedIntegrationType.targetUrl;
|
||||
this.active = this.selectedIntegrationType.active;
|
||||
},
|
||||
dismissFeedback() {
|
||||
this.serverError = null;
|
||||
this.feedback = { ...this.feedback, feedbackMessage: null };
|
||||
this.isFeedbackDismissed = false;
|
||||
},
|
||||
resetKey(key) {
|
||||
const fn = key === 'PROMETHEUS' ? this.resetPrometheusKey() : this.resetGenericKey();
|
||||
|
||||
return fn
|
||||
.then(({ data: { token } }) => {
|
||||
this.token = token;
|
||||
this.setFeedback({ feedbackMessage: this.$options.i18n.tokenRest, variant: 'success' });
|
||||
})
|
||||
.catch(() => {
|
||||
this.setFeedback({ feedbackMessage: this.$options.i18n.errorKeyMsg, variant: 'danger' });
|
||||
});
|
||||
},
|
||||
resetGenericKey() {
|
||||
this.dismissFeedback();
|
||||
return service.updateGenericKey({
|
||||
endpoint: this.generic.formPath,
|
||||
params: { service: { token: '' } },
|
||||
});
|
||||
},
|
||||
resetPrometheusKey() {
|
||||
return service.updatePrometheusKey({ endpoint: this.prometheus.prometheusResetKeyPath });
|
||||
},
|
||||
toggleService(value) {
|
||||
this.canSaveForm = true;
|
||||
this.active = value;
|
||||
},
|
||||
toggle(value) {
|
||||
return this.isPrometheus ? this.togglePrometheusActive(value) : this.toggleActivated(value);
|
||||
},
|
||||
toggleActivated(value) {
|
||||
this.loading = true;
|
||||
const path = this.isOpsgenie ? this.opsgenie.formPath : this.generic.formPath;
|
||||
return service
|
||||
.updateGenericActive({
|
||||
endpoint: path,
|
||||
params: this.isOpsgenie
|
||||
? { service: { opsgenie_mvc_target_url: this.targetUrl, opsgenie_mvc_enabled: value } }
|
||||
: { service: { active: value } },
|
||||
})
|
||||
.then(() => this.notifySuccessAndReload())
|
||||
.catch(({ response: { data: { errors } = {} } = {} }) => {
|
||||
this.createUserErrorMessage(errors);
|
||||
this.setFeedback({
|
||||
feedbackMessage: this.$options.i18n.errorMsg,
|
||||
variant: 'danger',
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
this.canSaveForm = false;
|
||||
});
|
||||
},
|
||||
reload() {
|
||||
if (!doesHashExistInUrl(sectionHash)) {
|
||||
window.location.hash = sectionHash;
|
||||
}
|
||||
window.location.reload();
|
||||
},
|
||||
togglePrometheusActive(value) {
|
||||
this.loading = true;
|
||||
return service
|
||||
.updatePrometheusActive({
|
||||
endpoint: this.prometheus.prometheusFormPath,
|
||||
params: {
|
||||
token: this.$options.csrf.token,
|
||||
config: value,
|
||||
url: this.targetUrl,
|
||||
redirect: window.location,
|
||||
},
|
||||
})
|
||||
.then(() => this.notifySuccessAndReload())
|
||||
.catch(({ response: { data: { errors } = {} } = {} }) => {
|
||||
this.createUserErrorMessage(errors);
|
||||
this.setFeedback({
|
||||
feedbackMessage: this.$options.i18n.errorMsg,
|
||||
variant: 'danger',
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
this.canSaveForm = false;
|
||||
});
|
||||
},
|
||||
notifySuccessAndReload() {
|
||||
createFlash({ message: this.$options.i18n.changesSaved, type: FLASH_TYPES.NOTICE });
|
||||
setTimeout(() => this.reload(), 1000);
|
||||
},
|
||||
setFeedback({ feedbackMessage, variant }) {
|
||||
this.feedback = { feedbackMessage, variant };
|
||||
},
|
||||
validateJson() {
|
||||
this.testAlert.error = null;
|
||||
try {
|
||||
JSON.parse(this.testAlert.json);
|
||||
} catch (e) {
|
||||
this.testAlert.error = JSON.stringify(e.message);
|
||||
}
|
||||
},
|
||||
validateTestAlert() {
|
||||
this.loading = true;
|
||||
this.dismissFeedback();
|
||||
this.validateJson();
|
||||
return service
|
||||
.updateTestAlert({
|
||||
endpoint: this.selectedIntegrationType.url,
|
||||
data: this.testAlert.json,
|
||||
token: this.selectedIntegrationType.token,
|
||||
})
|
||||
.then(() => {
|
||||
this.setFeedback({
|
||||
feedbackMessage: this.$options.i18n.testAlertSuccess,
|
||||
variant: 'success',
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
this.setFeedback({
|
||||
feedbackMessage: this.$options.i18n.testAlertFailed,
|
||||
variant: 'danger',
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
onSubmit() {
|
||||
this.dismissFeedback();
|
||||
this.toggle(this.active);
|
||||
},
|
||||
onReset() {
|
||||
this.testAlert.json = null;
|
||||
this.dismissFeedback();
|
||||
this.targetUrl = this.selectedIntegrationType.targetUrl;
|
||||
|
||||
if (this.canSaveForm) {
|
||||
this.canSaveForm = false;
|
||||
this.active = this.selectedIntegrationType.active;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-form @submit.prevent="onSubmit" @reset.prevent="onReset">
|
||||
<h5 class="gl-font-lg gl-my-5">{{ $options.i18n.integrationsLabel }}</h5>
|
||||
|
||||
<gl-alert v-if="showFeedbackMsg" :variant="feedback.variant" @dismiss="dismissFeedback">
|
||||
{{ feedback.feedbackMessage }}
|
||||
<br />
|
||||
<i v-if="serverError">{{ __('Error message:') }} {{ serverError }}</i>
|
||||
<gl-button
|
||||
v-if="showAlertSave"
|
||||
variant="danger"
|
||||
category="primary"
|
||||
class="gl-display-block gl-mt-3"
|
||||
@click="toggle(active)"
|
||||
>
|
||||
{{ __('Save anyway') }}
|
||||
</gl-button>
|
||||
</gl-alert>
|
||||
|
||||
<div data-testid="alert-settings-description">
|
||||
<p v-for="section in sections" :key="section.text">
|
||||
<gl-sprintf :message="section.text">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<gl-form-group label-for="integration-type" :label="$options.i18n.integration">
|
||||
<gl-form-select
|
||||
id="integration-type"
|
||||
v-model="selectedIntegration"
|
||||
:options="options"
|
||||
data-testid="alert-settings-select"
|
||||
@change="resetFormValues"
|
||||
/>
|
||||
<span class="gl-text-gray-500">
|
||||
<gl-sprintf :message="$options.i18n.integrationsInfo">
|
||||
<template #link="{ content }">
|
||||
<gl-link
|
||||
class="gl-display-inline-block"
|
||||
href="https://gitlab.com/groups/gitlab-org/-/epics/4390"
|
||||
target="_blank"
|
||||
>{{ content }}</gl-link
|
||||
>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<gl-form-group :label="$options.i18n.activeLabel" label-for="active">
|
||||
<toggle-button
|
||||
id="active"
|
||||
:disabled-input="loading"
|
||||
:is-loading="loading"
|
||||
:value="active"
|
||||
@change="toggleService"
|
||||
/>
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
v-if="isOpsgenie || isPrometheus"
|
||||
:label="$options.i18n.apiBaseUrlLabel"
|
||||
label-for="api-url"
|
||||
>
|
||||
<gl-form-input
|
||||
id="api-url"
|
||||
v-model="targetUrl"
|
||||
type="url"
|
||||
:placeholder="baseUrlPlaceholder"
|
||||
:disabled="!active"
|
||||
/>
|
||||
<span class="gl-text-gray-500">
|
||||
{{ $options.i18n.apiBaseUrlHelpText }}
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<template v-if="!isOpsgenie">
|
||||
<gl-form-group :label="$options.i18n.urlLabel" label-for="url">
|
||||
<gl-form-input-group id="url" readonly :value="selectedIntegrationType.url">
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="selectedIntegrationType.url"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
<span class="gl-text-gray-500">
|
||||
{{ prometheusInfo }}
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<gl-form-group :label="$options.i18n.tokenLabel" label-for="authorization-key">
|
||||
<gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="token">
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="token"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
<gl-button v-gl-modal.tokenModal :disabled="!active" class="gl-mt-3">{{
|
||||
$options.i18n.resetKey
|
||||
}}</gl-button>
|
||||
<gl-modal
|
||||
modal-id="tokenModal"
|
||||
:title="$options.i18n.resetKey"
|
||||
:ok-title="$options.i18n.resetKey"
|
||||
ok-variant="danger"
|
||||
@ok="selectedIntegrationType.resetKey"
|
||||
>
|
||||
{{ $options.i18n.restKeyInfo }}
|
||||
</gl-modal>
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
:label="$options.i18n.alertJson"
|
||||
label-for="alert-json"
|
||||
:invalid-feedback="testAlert.error"
|
||||
>
|
||||
<gl-form-textarea
|
||||
id="alert-json"
|
||||
v-model.trim="testAlert.json"
|
||||
:disabled="!active"
|
||||
:state="jsonIsValid"
|
||||
:placeholder="$options.i18n.alertJsonPlaceholder"
|
||||
rows="6"
|
||||
max-rows="10"
|
||||
/>
|
||||
</gl-form-group>
|
||||
|
||||
<gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{
|
||||
$options.i18n.testAlertInfo
|
||||
}}</gl-button>
|
||||
</template>
|
||||
<div class="footer-block row-content-block gl-display-flex gl-justify-content-space-between">
|
||||
<gl-button variant="success" category="primary" :disabled="!canSaveConfig" @click="onSubmit">
|
||||
{{ __('Save changes') }}
|
||||
</gl-button>
|
||||
<gl-button category="primary" :disabled="!canSaveConfig" @click="onReset">
|
||||
{{ __('Cancel') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</gl-form>
|
||||
</template>
|
|
@ -1,7 +1,6 @@
|
|||
<script>
|
||||
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { fetchPolicies } from '~/lib/graphql';
|
||||
import createFlash, { FLASH_TYPES } from '~/flash';
|
||||
import getIntegrationsQuery from '../graphql/queries/get_integrations.query.graphql';
|
||||
|
@ -15,7 +14,6 @@ import resetHttpTokenMutation from '../graphql/mutations/reset_http_token.mutati
|
|||
import resetPrometheusTokenMutation from '../graphql/mutations/reset_prometheus_token.mutation.graphql';
|
||||
import updateCurrentIntergrationMutation from '../graphql/mutations/update_current_intergration.mutation.graphql';
|
||||
import IntegrationsList from './alerts_integrations_list.vue';
|
||||
import SettingsFormOld from './alerts_settings_form_old.vue';
|
||||
import SettingsFormNew from './alerts_settings_form_new.vue';
|
||||
import { typeSet } from '../constants';
|
||||
import {
|
||||
|
@ -44,10 +42,8 @@ export default {
|
|||
GlLink,
|
||||
GlSprintf,
|
||||
IntegrationsList,
|
||||
SettingsFormOld,
|
||||
SettingsFormNew,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
inject: {
|
||||
generic: {
|
||||
default: {},
|
||||
|
@ -101,20 +97,6 @@ export default {
|
|||
loading() {
|
||||
return this.$apollo.queries.integrations.loading;
|
||||
},
|
||||
integrationsOptionsOld() {
|
||||
return [
|
||||
{
|
||||
name: s__('AlertSettings|HTTP endpoint'),
|
||||
type: s__('AlertsIntegrations|HTTP endpoint'),
|
||||
active: this.generic.active,
|
||||
},
|
||||
{
|
||||
name: s__('AlertSettings|External Prometheus'),
|
||||
type: s__('AlertsIntegrations|Prometheus'),
|
||||
active: this.prometheus.active,
|
||||
},
|
||||
];
|
||||
},
|
||||
canAddIntegration() {
|
||||
return this.multiIntegrations || this.integrations?.list?.length < 2;
|
||||
},
|
||||
|
@ -310,13 +292,12 @@ export default {
|
|||
</gl-alert>
|
||||
<integrations-list
|
||||
v-else
|
||||
:integrations="glFeatures.httpIntegrationsList ? integrations.list : integrationsOptionsOld"
|
||||
:integrations="integrations.list"
|
||||
:loading="loading"
|
||||
@edit-integration="editIntegration"
|
||||
@delete-integration="deleteIntegration"
|
||||
/>
|
||||
<settings-form-new
|
||||
v-if="glFeatures.httpIntegrationsList"
|
||||
:loading="isUpdating"
|
||||
:can-add-integration="canAddIntegration"
|
||||
:can-manage-opsgenie="canManageOpsgenie"
|
||||
|
@ -326,6 +307,5 @@ export default {
|
|||
@clear-current-integration="clearCurrentIntegration"
|
||||
@test-payload-failure="testPayloadFailure"
|
||||
/>
|
||||
<settings-form-old v-else />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -2,30 +2,9 @@
|
|||
import axios from '~/lib/utils/axios_utils';
|
||||
|
||||
export default {
|
||||
// TODO: All this code save updateTestAlert will be deleted as part of: https://gitlab.com/gitlab-org/gitlab/-/issues/255501
|
||||
updateGenericKey({ endpoint, params }) {
|
||||
return axios.put(endpoint, params);
|
||||
},
|
||||
updatePrometheusKey({ endpoint }) {
|
||||
return axios.post(endpoint);
|
||||
},
|
||||
updateGenericActive({ endpoint, params }) {
|
||||
return axios.put(endpoint, params);
|
||||
},
|
||||
updatePrometheusActive({ endpoint, params: { token, config, url, redirect } }) {
|
||||
const data = new FormData();
|
||||
data.set('_method', 'put');
|
||||
data.set('authenticity_token', token);
|
||||
data.set('service[manual_configuration]', config);
|
||||
data.set('service[api_url]', url);
|
||||
data.set('redirect_to', redirect);
|
||||
|
||||
return axios.post(endpoint, data, {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
});
|
||||
},
|
||||
updateTestAlert({ endpoint, data, token }) {
|
||||
return axios.post(endpoint, data, {
|
||||
headers: {
|
||||
|
|
|
@ -64,9 +64,9 @@ export default {
|
|||
<gl-button
|
||||
v-if="canUpdate"
|
||||
variant="link"
|
||||
class="gl-text-gray-900!"
|
||||
class="gl-text-gray-900! js-sidebar-dropdown-toggle"
|
||||
data-testid="edit-button"
|
||||
@click="expand()"
|
||||
@click="expand"
|
||||
>
|
||||
{{ __('Edit') }}
|
||||
</gl-button>
|
||||
|
@ -75,7 +75,7 @@ export default {
|
|||
<slot name="collapsed">{{ __('None') }}</slot>
|
||||
</div>
|
||||
<div v-show="edit" data-testid="expanded-content">
|
||||
<slot></slot>
|
||||
<slot :edit="edit"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -92,7 +92,7 @@ export default {
|
|||
@close="removeLabel(label.id)"
|
||||
/>
|
||||
</template>
|
||||
<template>
|
||||
<template #default="{ edit }">
|
||||
<labels-select
|
||||
ref="labelsSelect"
|
||||
:allow-label-edit="false"
|
||||
|
@ -105,6 +105,7 @@ export default {
|
|||
:labels-filter-base-path="labelsFilterBasePath"
|
||||
:labels-list-title="__('Select label')"
|
||||
:dropdown-button-text="__('Choose labels')"
|
||||
:is-editing="edit"
|
||||
variant="embedded"
|
||||
class="gl-display-block labels gl-w-full"
|
||||
@updateSelectedLabels="setLabels"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script>
|
||||
import { mapState, mapMutations } from 'vuex';
|
||||
import { GlAlert } from '@gitlab/ui';
|
||||
import MembersTable from '~/vue_shared/components/members/table/members_table.vue';
|
||||
import MembersTable from '~/members/components/table/members_table.vue';
|
||||
import { scrollToElement } from '~/lib/utils/common_utils';
|
||||
import { HIDE_ERROR } from '~/vuex_shared/modules/members/mutation_types';
|
||||
import { HIDE_ERROR } from '~/members/store/mutation_types';
|
||||
|
||||
export default {
|
||||
name: 'GroupMembersApp',
|
||||
|
|
|
@ -3,7 +3,7 @@ import Vuex from 'vuex';
|
|||
import { GlToast } from '@gitlab/ui';
|
||||
import { parseDataAttributes } from 'ee_else_ce/groups/members/utils';
|
||||
import App from './components/app.vue';
|
||||
import membersModule from '~/vuex_shared/modules/members';
|
||||
import membersStore from '~/members/store';
|
||||
|
||||
export const initGroupMembersApp = (el, tableFields, tableAttrs, requestFormatter) => {
|
||||
if (!el) {
|
||||
|
@ -13,15 +13,15 @@ export const initGroupMembersApp = (el, tableFields, tableAttrs, requestFormatte
|
|||
Vue.use(Vuex);
|
||||
Vue.use(GlToast);
|
||||
|
||||
const store = new Vuex.Store({
|
||||
...membersModule({
|
||||
const store = new Vuex.Store(
|
||||
membersStore({
|
||||
...parseDataAttributes(el),
|
||||
currentUserId: gon.current_user_id || null,
|
||||
tableFields,
|
||||
tableAttrs,
|
||||
requestFormatter,
|
||||
}),
|
||||
});
|
||||
);
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
|
|
|
@ -218,23 +218,36 @@ export const isMetaKey = e => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
|
|||
export const isMetaClick = e => e.metaKey || e.ctrlKey || e.which === 2;
|
||||
|
||||
export const contentTop = () => {
|
||||
const perfBar = $('#js-peek').outerHeight() || 0;
|
||||
const mrTabsHeight = $('.merge-request-tabs').outerHeight() || 0;
|
||||
const headerHeight = $('.navbar-gitlab').outerHeight() || 0;
|
||||
const diffFilesChanged = $('.js-diff-files-changed').outerHeight() || 0;
|
||||
const isDesktop = breakpointInstance.isDesktop();
|
||||
const diffFileTitleBar =
|
||||
(isDesktop && $('.diff-file .file-title-flex-parent:visible').outerHeight()) || 0;
|
||||
const compareVersionsHeaderHeight = (isDesktop && $('.mr-version-controls').outerHeight()) || 0;
|
||||
const heightCalculators = [
|
||||
() => $('#js-peek').outerHeight(),
|
||||
() => $('.navbar-gitlab').outerHeight(),
|
||||
() => $('.merge-request-tabs').outerHeight(),
|
||||
() => $('.js-diff-files-changed').outerHeight(),
|
||||
() => {
|
||||
const isDesktop = breakpointInstance.isDesktop();
|
||||
const diffsTabIsActive = window.mrTabs?.currentAction === 'diffs';
|
||||
let size;
|
||||
|
||||
return (
|
||||
perfBar +
|
||||
mrTabsHeight +
|
||||
headerHeight +
|
||||
diffFilesChanged +
|
||||
diffFileTitleBar +
|
||||
compareVersionsHeaderHeight
|
||||
);
|
||||
if (isDesktop && diffsTabIsActive) {
|
||||
size = $('.diff-file .file-title-flex-parent:visible').outerHeight();
|
||||
}
|
||||
|
||||
return size;
|
||||
},
|
||||
() => {
|
||||
let size;
|
||||
|
||||
if (breakpointInstance.isDesktop()) {
|
||||
size = $('.mr-version-controls').outerHeight();
|
||||
}
|
||||
|
||||
return size;
|
||||
},
|
||||
];
|
||||
|
||||
return heightCalculators.reduce((totalHeight, calculator) => {
|
||||
return totalHeight + (calculator() || 0);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
export const scrollToElement = (element, options = {}) => {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import LeaveModal from '../modals/leave_modal.vue';
|
||||
import { LEAVE_MODAL_ID } from '../constants';
|
||||
import { LEAVE_MODAL_ID } from '../../constants';
|
||||
|
||||
export default {
|
||||
name: 'LeaveButton',
|
|
@ -11,7 +11,7 @@ export default {
|
|||
RemoveMemberButton,
|
||||
LeaveButton,
|
||||
LdapOverrideButton: () =>
|
||||
import('ee_component/vue_shared/components/members/ldap/ldap_override_button.vue'),
|
||||
import('ee_component/members/components/ldap/ldap_override_button.vue'),
|
||||
},
|
||||
props: {
|
||||
member: {
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlAvatarLink, GlAvatarLabeled } from '@gitlab/ui';
|
||||
import { AVATAR_SIZE } from '../constants';
|
||||
import { AVATAR_SIZE } from '../../constants';
|
||||
|
||||
export default {
|
||||
name: 'GroupAvatar',
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlAvatarLabeled } from '@gitlab/ui';
|
||||
import { AVATAR_SIZE } from '../constants';
|
||||
import { AVATAR_SIZE } from '../../constants';
|
||||
|
||||
export default {
|
||||
name: 'InviteAvatar',
|
|
@ -5,9 +5,9 @@ import {
|
|||
GlBadge,
|
||||
GlSafeHtmlDirective as SafeHtml,
|
||||
} from '@gitlab/ui';
|
||||
import { generateBadges } from 'ee_else_ce/vue_shared/components/members/utils';
|
||||
import { generateBadges } from 'ee_else_ce/members/utils';
|
||||
import { __ } from '~/locale';
|
||||
import { AVATAR_SIZE } from '../constants';
|
||||
import { AVATAR_SIZE } from '../../constants';
|
||||
import { glEmojiTag } from '~/emoji';
|
||||
|
||||
export default {
|
|
@ -3,7 +3,7 @@ import { mapState } from 'vuex';
|
|||
import { GlModal, GlForm, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
import { LEAVE_MODAL_ID } from '../constants';
|
||||
import { LEAVE_MODAL_ID } from '../../constants';
|
||||
|
||||
export default {
|
||||
name: 'LeaveModal',
|
|
@ -3,7 +3,7 @@ import { mapState, mapActions } from 'vuex';
|
|||
import { GlModal, GlSprintf, GlForm } from '@gitlab/ui';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
import { REMOVE_GROUP_LINK_MODAL_ID } from '../constants';
|
||||
import { REMOVE_GROUP_LINK_MODAL_ID } from '../../constants';
|
||||
|
||||
export default {
|
||||
name: 'RemoveGroupLinkModal',
|
|
@ -6,7 +6,7 @@ import {
|
|||
formatDate,
|
||||
getDayDifference,
|
||||
} from '~/lib/utils/datetime_utility';
|
||||
import { DAYS_TO_EXPIRE_SOON } from '../constants';
|
||||
import { DAYS_TO_EXPIRE_SOON } from '../../constants';
|
||||
|
||||
export default {
|
||||
name: 'ExpiresAt',
|
|
@ -3,7 +3,7 @@ import UserActionButtons from '../action_buttons/user_action_buttons.vue';
|
|||
import GroupActionButtons from '../action_buttons/group_action_buttons.vue';
|
||||
import InviteActionButtons from '../action_buttons/invite_action_buttons.vue';
|
||||
import AccessRequestActionButtons from '../action_buttons/access_request_action_buttons.vue';
|
||||
import { MEMBER_TYPES } from '../constants';
|
||||
import { MEMBER_TYPES } from '../../constants';
|
||||
|
||||
export default {
|
||||
name: 'MemberActionButtons',
|
|
@ -1,14 +1,9 @@
|
|||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import { GlTable, GlBadge } from '@gitlab/ui';
|
||||
import MembersTableCell from 'ee_else_ce/vue_shared/components/members/table/members_table_cell.vue';
|
||||
import {
|
||||
canOverride,
|
||||
canRemove,
|
||||
canResend,
|
||||
canUpdate,
|
||||
} from 'ee_else_ce/vue_shared/components/members/utils';
|
||||
import { FIELDS } from '../constants';
|
||||
import MembersTableCell from 'ee_else_ce/members/components/table/members_table_cell.vue';
|
||||
import { canOverride, canRemove, canResend, canUpdate } from 'ee_else_ce/members/utils';
|
||||
import { FIELDS } from '../../constants';
|
||||
import initUserPopovers from '~/user_popovers';
|
||||
import MemberAvatar from './member_avatar.vue';
|
||||
import MemberSource from './member_source.vue';
|
||||
|
@ -34,9 +29,7 @@ export default {
|
|||
RemoveGroupLinkModal,
|
||||
ExpirationDatepicker,
|
||||
LdapOverrideConfirmationModal: () =>
|
||||
import(
|
||||
'ee_component/vue_shared/components/members/ldap/ldap_override_confirmation_modal.vue'
|
||||
),
|
||||
import('ee_component/members/components/ldap/ldap_override_confirmation_modal.vue'),
|
||||
},
|
||||
computed: {
|
||||
...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId', 'sourceId']),
|
|
@ -1,7 +1,14 @@
|
|||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import { MEMBER_TYPES } from '../constants';
|
||||
import { isGroup, isDirectMember, isCurrentUser, canRemove, canResend, canUpdate } from '../utils';
|
||||
import { MEMBER_TYPES } from '../../constants';
|
||||
import {
|
||||
isGroup,
|
||||
isDirectMember,
|
||||
isCurrentUser,
|
||||
canRemove,
|
||||
canResend,
|
||||
canUpdate,
|
||||
} from '../../utils';
|
||||
|
||||
export default {
|
||||
name: 'MembersTableCell',
|
|
@ -9,8 +9,7 @@ export default {
|
|||
components: {
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
LdapDropdownItem: () =>
|
||||
import('ee_component/vue_shared/components/members/ldap/ldap_dropdown_item.vue'),
|
||||
LdapDropdownItem: () => import('ee_component/members/components/ldap/ldap_dropdown_item.vue'),
|
||||
},
|
||||
props: {
|
||||
member: {
|
|
@ -0,0 +1,9 @@
|
|||
import createState from 'ee_else_ce/members/store/state';
|
||||
import mutations from 'ee_else_ce/members/store/mutations';
|
||||
import * as actions from 'ee_else_ce/members/store/actions';
|
||||
|
||||
export default initialState => ({
|
||||
state: createState(initialState),
|
||||
actions,
|
||||
mutations,
|
||||
});
|
|
@ -1,16 +1,17 @@
|
|||
import { mapGetters, mapActions, mapState } from 'vuex';
|
||||
import { scrollToElementWithContext } from '~/lib/utils/common_utils';
|
||||
import { scrollToElementWithContext, scrollToElement } from '~/lib/utils/common_utils';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
/**
|
||||
* @param {string} selector
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function scrollTo(selector) {
|
||||
function scrollTo(selector, { withoutContext = false } = {}) {
|
||||
const el = document.querySelector(selector);
|
||||
const scrollFunction = withoutContext ? scrollToElement : scrollToElementWithContext;
|
||||
|
||||
if (el) {
|
||||
scrollToElementWithContext(el);
|
||||
scrollFunction(el);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -35,7 +36,7 @@ function diffsJump({ expandDiscussion }, id) {
|
|||
function discussionJump({ expandDiscussion }, id) {
|
||||
const selector = `div.discussion[data-discussion-id="${id}"]`;
|
||||
expandDiscussion({ discussionId: id });
|
||||
return scrollTo(selector);
|
||||
return scrollTo(selector, { withoutContext: true });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -796,7 +796,7 @@ UsersSelect.prototype.renderRowAvatar = function(issuableType, user, img) {
|
|||
|
||||
const mergeIcon =
|
||||
issuableType === 'merge_request' && !user.can_merge
|
||||
? '<i class="fa fa-exclamation-triangle merge-icon"></i>'
|
||||
? `${spriteIcon('warning-solid', 's12 merge-icon')}`
|
||||
: '';
|
||||
|
||||
return `<span class="position-relative mr-2">
|
||||
|
|
|
@ -105,6 +105,11 @@ export default {
|
|||
required: false,
|
||||
default: __('Manage group labels'),
|
||||
},
|
||||
isEditing: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -131,6 +136,11 @@ export default {
|
|||
showDropdownContents(showDropdownContents) {
|
||||
this.setContentIsOnViewport(showDropdownContents);
|
||||
},
|
||||
isEditing(newVal) {
|
||||
if (newVal) {
|
||||
this.toggleDropdownContents();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.setInitialState({
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import createState from 'ee_else_ce/vuex_shared/modules/members/state';
|
||||
import mutations from 'ee_else_ce/vuex_shared/modules/members/mutations';
|
||||
import * as actions from 'ee_else_ce/vuex_shared/modules/members/actions';
|
||||
|
||||
export default initialState => ({
|
||||
namespaced: true,
|
||||
state: createState(initialState),
|
||||
actions,
|
||||
mutations,
|
||||
});
|
|
@ -7,7 +7,6 @@ module Projects
|
|||
before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token]
|
||||
|
||||
before_action do
|
||||
push_frontend_feature_flag(:http_integrations_list, @project)
|
||||
push_frontend_feature_flag(:multiple_http_integrations_custom_mapping, @project)
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
.settings-header
|
||||
%h4
|
||||
= _('Metrics - Prometheus')
|
||||
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
|
||||
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
|
||||
= expanded_by_default? ? _('Collapse') : _('Expand')
|
||||
%p
|
||||
= _('Enable and configure Prometheus metrics.')
|
||||
|
@ -17,7 +17,7 @@
|
|||
.settings-header
|
||||
%h4
|
||||
= _('Metrics - Grafana')
|
||||
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
|
||||
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
|
||||
= expanded_by_default? ? _('Collapse') : _('Expand')
|
||||
%p
|
||||
= _('Enable and configure Grafana.')
|
||||
|
@ -28,7 +28,7 @@
|
|||
.settings-header
|
||||
%h4
|
||||
= _('Profiling - Performance bar')
|
||||
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
|
||||
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
|
||||
= expanded_by_default? ? _('Collapse') : _('Expand')
|
||||
%p
|
||||
= _('Enable access to the Performance Bar for a given group.')
|
||||
|
@ -42,7 +42,7 @@
|
|||
.settings-header#usage-statistics
|
||||
%h4
|
||||
= _('Usage statistics')
|
||||
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
|
||||
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
|
||||
= expanded_by_default? ? _('Collapse') : _('Expand')
|
||||
%p
|
||||
= _('Enable or disable version check and usage ping.')
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
%span.runner-state.runner-state-specific
|
||||
Specific
|
||||
|
||||
- page_title _("Runners")
|
||||
- page_title @runner.short_sha
|
||||
- add_to_breadcrumbs _("Runners"), admin_runners_path
|
||||
- breadcrumb_title "##{@runner.id}"
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
= image_tag 'novice.svg', width: '78', height: '78', alt: ''
|
||||
%div
|
||||
%p.gl-font-lg.gl-font-weight-bold.gl-mb-2= _('Novice')
|
||||
%p= _('I’m not very familiar with the basics of project management and DevOps.')
|
||||
= link_to _('Show me everything'), users_sign_up_experience_level_path(experience_level: :novice, namespace_path: params[:namespace_path]), method: :patch, class: 'stretched-link'
|
||||
%p= _('I’m not familiar with the basics of DevOps.')
|
||||
= link_to _('Show me the basics'), users_sign_up_experience_level_path(experience_level: :novice, namespace_path: params[:namespace_path]), method: :patch, class: 'stretched-link'
|
||||
|
||||
.card
|
||||
.card-body.gl-display-flex.gl-py-8.gl-pr-5.gl-pl-7
|
||||
|
@ -24,5 +24,5 @@
|
|||
= image_tag 'experienced.svg', width: '78', height: '78', alt: ''
|
||||
%div
|
||||
%p.gl-font-lg.gl-font-weight-bold.gl-mb-2= _('Experienced')
|
||||
%p= _('I’m familiar with the basics of project management and DevOps.')
|
||||
= link_to _('Show me more advanced stuff'), users_sign_up_experience_level_path(experience_level: :experienced, namespace_path: params[:namespace_path]), method: :patch, class: 'stretched-link'
|
||||
%p= _('I’m familiar with the basics of DevOps.')
|
||||
= link_to _('Show me advanced features'), users_sign_up_experience_level_path(experience_level: :experienced, namespace_path: params[:namespace_path]), method: :patch, class: 'stretched-link'
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Remove http_integrations_list feature flag
|
||||
merge_request: 48030
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Replace Runner Page Title with Runner’s Hash
|
||||
merge_request: 44854
|
||||
author: Kev @KevSlashNull
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Scroll exactly to the top of a discussion on the MR Overview tab
|
||||
merge_request: 47970
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Iterate on the copy in the “Novice or Experienced” page of the registration
|
||||
onboarding flow.
|
||||
merge_request: 48086
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Replace fa-exclamation-triangle in users select
|
||||
merge_request: 48116
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fixed editing labels on the swimlanes sidebar
|
||||
merge_request: 47946
|
||||
author:
|
||||
type: fixed
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: http_integrations_list
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45993
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255502
|
||||
milestone: '13.6'
|
||||
type: development
|
||||
group: group::health
|
||||
default_enabled: false
|
|
@ -2417,6 +2417,18 @@ Read more in the [Project import/export](project_import_export.md) documentation
|
|||
|
||||
Read more in the [Project members](members.md) documentation.
|
||||
|
||||
## Configure pull mirroring for a project **(STARTER)**
|
||||
|
||||
> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 11.2.
|
||||
|
||||
Configure pull mirroring while [creating a new project](#create-project) or [updating an existing project](#edit-project) using the API if the remote repository is publicly accessible or via `username/password` authentication. In case your HTTP repository is not publicly accessible, you can add the authentication information to the URL: `https://username:password@gitlab.company.com/group/project.git`, where password is a [personal access token](../user/profile/personal_access_tokens.md) with the API scope enabled.
|
||||
|
||||
The relevant API parameters to update are:
|
||||
|
||||
- `import_url`: URL of remote repository being mirrored (with `username:password` if needed).
|
||||
- `mirror`: Enables pull mirroring on project when set to `true`.
|
||||
- `only_mirror_protected_branches`: Set to `true` for protected branches.
|
||||
|
||||
## Start the pull mirroring process for a Project **(STARTER)**
|
||||
|
||||
> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Graphql
|
||||
module ConnectionCollectionMethods
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
delegate :to_a, :size, :include?, :empty?, to: :nodes
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Graphql
|
||||
module ConnectionRedaction
|
||||
class RedactionState
|
||||
attr_reader :redactor
|
||||
attr_reader :redacted_nodes
|
||||
|
||||
def redactor=(redactor)
|
||||
@redactor = redactor
|
||||
@redacted_nodes = nil
|
||||
end
|
||||
|
||||
def redacted(&block)
|
||||
@redacted_nodes ||= redactor.present? ? redactor.redact(yield) : yield
|
||||
end
|
||||
end
|
||||
|
||||
delegate :redactor=, to: :redaction_state
|
||||
|
||||
def nodes
|
||||
redaction_state.redacted { super.to_a }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def redaction_state
|
||||
@redaction_state ||= RedactionState.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# We use the Keyset / Stable cursor connection by default for ActiveRecord::Relation.
|
||||
# However, there are times when that may not be powerful enough (yet), and we
|
||||
# want to use standard offset pagination.
|
||||
module Gitlab
|
||||
module Graphql
|
||||
module Pagination
|
||||
class ArrayConnection < ::GraphQL::Pagination::ArrayConnection
|
||||
prepend ::Gitlab::Graphql::ConnectionRedaction
|
||||
include ::Gitlab::Graphql::ConnectionCollectionMethods
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -12,6 +12,10 @@ module Gitlab
|
|||
schema.connections.add(
|
||||
Gitlab::Graphql::ExternallyPaginatedArray,
|
||||
Gitlab::Graphql::Pagination::ExternallyPaginatedArrayConnection)
|
||||
|
||||
schema.connections.add(
|
||||
Array,
|
||||
Gitlab::Graphql::Pagination::ArrayConnection)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,9 @@ module Gitlab
|
|||
module Graphql
|
||||
module Pagination
|
||||
class ExternallyPaginatedArrayConnection < GraphQL::Pagination::ArrayConnection
|
||||
include ::Gitlab::Graphql::ConnectionCollectionMethods
|
||||
prepend ::Gitlab::Graphql::ConnectionRedaction
|
||||
|
||||
def start_cursor
|
||||
items.previous_cursor
|
||||
end
|
||||
|
|
|
@ -31,6 +31,8 @@ module Gitlab
|
|||
module Keyset
|
||||
class Connection < GraphQL::Pagination::ActiveRecordRelationConnection
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include ::Gitlab::Graphql::ConnectionCollectionMethods
|
||||
prepend ::Gitlab::Graphql::ConnectionRedaction
|
||||
|
||||
# rubocop: disable Naming/PredicateName
|
||||
# https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo.Fields
|
||||
|
|
|
@ -7,6 +7,8 @@ module Gitlab
|
|||
module Graphql
|
||||
module Pagination
|
||||
class OffsetActiveRecordRelationConnection < GraphQL::Pagination::ActiveRecordRelationConnection
|
||||
prepend ::Gitlab::Graphql::ConnectionRedaction
|
||||
include ::Gitlab::Graphql::ConnectionCollectionMethods
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2565,9 +2565,6 @@ msgstr ""
|
|||
msgid "AlertSettings|HTTP Endpoint"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|HTTP endpoint"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields."
|
||||
msgstr ""
|
||||
|
||||
|
@ -2688,9 +2685,6 @@ msgstr ""
|
|||
msgid "AlertsIntegrations|Current integrations"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertsIntegrations|HTTP endpoint"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertsIntegrations|Integration Name"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2700,9 +2694,6 @@ msgstr ""
|
|||
msgid "AlertsIntegrations|No integrations have been added yet"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertsIntegrations|Prometheus"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
|
||||
msgstr ""
|
||||
|
||||
|
@ -9445,6 +9436,12 @@ msgstr ""
|
|||
msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|Add a segment to get started"
|
||||
msgstr ""
|
||||
|
||||
|
@ -9454,6 +9451,9 @@ msgstr ""
|
|||
msgid "DevopsAdoption|Approvals"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|Create new segment"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|Deploys"
|
||||
msgstr ""
|
||||
|
||||
|
@ -9466,6 +9466,15 @@ msgstr ""
|
|||
msgid "DevopsAdoption|MRs"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|My segment"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|Name"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|New segment"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|Pipelines"
|
||||
msgstr ""
|
||||
|
||||
|
@ -10827,9 +10836,6 @@ msgstr ""
|
|||
msgid "Error loading viewer"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error message:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error occurred when fetching sidebar data"
|
||||
msgstr ""
|
||||
|
||||
|
@ -15254,10 +15260,10 @@ msgstr ""
|
|||
msgid "Iteration|cannot be more than 500 years in the future"
|
||||
msgstr ""
|
||||
|
||||
msgid "I’m familiar with the basics of project management and DevOps."
|
||||
msgid "I’m familiar with the basics of DevOps."
|
||||
msgstr ""
|
||||
|
||||
msgid "I’m not very familiar with the basics of project management and DevOps."
|
||||
msgid "I’m not familiar with the basics of DevOps."
|
||||
msgstr ""
|
||||
|
||||
msgid "Jaeger URL"
|
||||
|
@ -18925,9 +18931,6 @@ msgstr ""
|
|||
msgid "OnDemandScans|Create a new site profile"
|
||||
msgstr ""
|
||||
|
||||
msgid "OnDemandScans|Create new DAST scan"
|
||||
msgstr ""
|
||||
|
||||
msgid "OnDemandScans|Manage profiles"
|
||||
msgstr ""
|
||||
|
||||
|
@ -18952,9 +18955,6 @@ msgstr ""
|
|||
msgid "OnDemandScans|Scanner profile"
|
||||
msgstr ""
|
||||
|
||||
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "OnDemandScans|Select one of the existing profiles"
|
||||
msgstr ""
|
||||
|
||||
|
@ -23567,9 +23567,6 @@ msgstr ""
|
|||
msgid "Save Push Rules"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save anyway"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save application"
|
||||
msgstr ""
|
||||
|
||||
|
@ -24926,13 +24923,13 @@ msgstr ""
|
|||
msgid "Show list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show me everything"
|
||||
msgid "Show me advanced features"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show me how to add a pipeline"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show me more advanced stuff"
|
||||
msgid "Show me the basics"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show only direct members"
|
||||
|
|
|
@ -22,12 +22,12 @@ module QA
|
|||
element :group_row
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/vue_shared/components/members/table/role_dropdown.vue' do
|
||||
view 'app/assets/javascripts/members/components/table/role_dropdown.vue' do
|
||||
element :access_level_dropdown
|
||||
element :access_level_link
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/vue_shared/components/members/action_buttons/remove_member_button.vue' do
|
||||
view 'app/assets/javascripts/members/components/action_buttons/remove_member_button.vue' do
|
||||
element :delete_member_button
|
||||
end
|
||||
|
||||
|
|
|
@ -282,6 +282,12 @@ RSpec.describe "Admin Runners" do
|
|||
visit admin_runner_path(runner)
|
||||
end
|
||||
|
||||
describe 'runner page breadcrumbs' do
|
||||
it 'contains the current runner’s short sha' do
|
||||
expect(page.find('h2')).to have_content(runner.short_sha)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'projects' do
|
||||
it 'contains project names' do
|
||||
expect(page).to have_content(@project1.full_name)
|
||||
|
|
|
@ -17,7 +17,7 @@ RSpec.describe 'Alert integrations settings form', :js do
|
|||
end
|
||||
|
||||
describe 'when viewing alert integrations as a maintainer' do
|
||||
context 'with feature flag enabled' do
|
||||
context 'with the default page permissions' do
|
||||
before do
|
||||
visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
|
||||
wait_for_requests
|
||||
|
@ -33,19 +33,6 @@ RSpec.describe 'Alert integrations settings form', :js do
|
|||
expect(page).to have_content('1. Select integration type')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with feature flag disabled' do
|
||||
before do
|
||||
stub_feature_flags(http_integrations_list: false)
|
||||
|
||||
visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'shows the old alerts setting form' do
|
||||
expect(page).to have_content('Webhook URL')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when viewing alert integrations as a developer' do
|
||||
|
|
|
@ -23,14 +23,14 @@ RSpec.describe 'Experience level screen' do
|
|||
|
||||
it 'shows the option for novice' do
|
||||
is_expected.to have_content('Novice')
|
||||
is_expected.to have_content('I’m not very familiar with the basics of project management and DevOps')
|
||||
is_expected.to have_content('Show me everything')
|
||||
is_expected.to have_content('I’m not familiar with the basics of DevOps')
|
||||
is_expected.to have_content('Show me the basics')
|
||||
end
|
||||
|
||||
it 'shows the option for experienced' do
|
||||
is_expected.to have_content('Experienced')
|
||||
is_expected.to have_content('I’m familiar with the basics of project management and DevOps')
|
||||
is_expected.to have_content('Show me more advanced stuff')
|
||||
is_expected.to have_content('I’m familiar with the basics of DevOps')
|
||||
is_expected.to have_content('Show me advanced features')
|
||||
end
|
||||
|
||||
it 'does not display any flash messages' do
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AlertsSettingsFormOld with default values renders the initial template 1`] = `
|
||||
"<gl-form-stub>
|
||||
<h5 class=\\"gl-font-lg gl-my-5\\"></h5>
|
||||
<!---->
|
||||
<div data-testid=\\"alert-settings-description\\">
|
||||
<p>
|
||||
<gl-sprintf-stub message=\\"You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.\\"></gl-sprintf-stub>
|
||||
</p>
|
||||
<p>
|
||||
<gl-sprintf-stub message=\\"Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.\\"></gl-sprintf-stub>
|
||||
</p>
|
||||
</div>
|
||||
<gl-form-group-stub label-for=\\"integration-type\\" label=\\"Integration\\">
|
||||
<gl-form-select-stub id=\\"integration-type\\" options=\\"[object Object],[object Object],[object Object]\\" data-testid=\\"alert-settings-select\\" value=\\"HTTP\\"></gl-form-select-stub> <span class=\\"gl-text-gray-500\\"><gl-sprintf-stub message=\\"Learn more about our our upcoming %{linkStart}integrations%{linkEnd}\\"></gl-sprintf-stub></span>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Active\\" label-for=\\"active\\">
|
||||
<toggle-button-stub id=\\"active\\"></toggle-button-stub>
|
||||
</gl-form-group-stub>
|
||||
<!---->
|
||||
<gl-form-group-stub label=\\"Webhook URL\\" label-for=\\"url\\">
|
||||
<gl-form-input-group-stub value=\\"/alerts/notify.json\\" predefinedoptions=\\"[object Object]\\" id=\\"url\\" readonly=\\"\\"></gl-form-input-group-stub> <span class=\\"gl-text-gray-500\\">
|
||||
|
||||
</span>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label-for=\\"authorization-key\\">
|
||||
<gl-form-input-group-stub value=\\"\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub>
|
||||
<gl-modal-stub modalid=\\"tokenModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
|
||||
Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.
|
||||
</gl-modal-stub>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Alert test payload\\" label-for=\\"alert-json\\">
|
||||
<gl-form-textarea-stub noresize=\\"true\\" id=\\"alert-json\\" disabled=\\"true\\" state=\\"true\\" placeholder=\\"Enter test alert JSON....\\" rows=\\"6\\" max-rows=\\"10\\"></gl-form-textarea-stub>
|
||||
</gl-form-group-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">Test alert payload</gl-button-stub>
|
||||
<div class=\\"footer-block row-content-block gl-display-flex gl-justify-content-space-between\\">
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
|
||||
Save changes
|
||||
</gl-button-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
|
||||
Cancel
|
||||
</gl-button-stub>
|
||||
</div>
|
||||
</gl-form-stub>"
|
||||
`;
|
|
@ -35,9 +35,6 @@ describe('AlertIntegrationsList', () => {
|
|||
integrations: mockIntegrations,
|
||||
...props,
|
||||
},
|
||||
provide: {
|
||||
glFeatures: { httpIntegrationsList: true },
|
||||
},
|
||||
stubs: {
|
||||
GlIcon: true,
|
||||
GlButton: true,
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlModal, GlAlert } from '@gitlab/ui';
|
||||
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_old.vue';
|
||||
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
|
||||
import { i18n } from '~/alerts_settings/constants';
|
||||
import service from '~/alerts_settings/services';
|
||||
import { defaultAlertSettingsConfig } from './util';
|
||||
|
||||
jest.mock('~/alerts_settings/services');
|
||||
|
||||
describe('AlertsSettingsFormOld', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = ({ methods } = {}, data) => {
|
||||
wrapper = shallowMount(AlertsSettingsForm, {
|
||||
data() {
|
||||
return { ...data };
|
||||
},
|
||||
provide: {
|
||||
...defaultAlertSettingsConfig,
|
||||
},
|
||||
methods,
|
||||
});
|
||||
};
|
||||
|
||||
const findSelect = () => wrapper.find('[data-testid="alert-settings-select"]');
|
||||
const findJsonInput = () => wrapper.find('#alert-json');
|
||||
const findUrl = () => wrapper.find('#url');
|
||||
const findAuthorizationKey = () => wrapper.find('#authorization-key');
|
||||
const findApiUrl = () => wrapper.find('#api-url');
|
||||
|
||||
beforeEach(() => {
|
||||
setFixtures(`
|
||||
<div>
|
||||
<span class="js-service-active-status fa fa-circle" data-value="true"></span>
|
||||
<span class="js-service-active-status fa fa-power-off" data-value="false"></span>
|
||||
</div>`);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (wrapper) {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
}
|
||||
});
|
||||
|
||||
describe('with default values', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('renders the initial template', () => {
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('reset key', () => {
|
||||
it('triggers resetKey method', () => {
|
||||
const resetKey = jest.fn();
|
||||
const methods = { resetKey };
|
||||
createComponent({ methods });
|
||||
|
||||
wrapper.find(GlModal).vm.$emit('ok');
|
||||
|
||||
expect(resetKey).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('updates the authorization key on success', () => {
|
||||
createComponent(
|
||||
{},
|
||||
{
|
||||
token: 'newToken',
|
||||
},
|
||||
);
|
||||
|
||||
expect(findAuthorizationKey().attributes('value')).toBe('newToken');
|
||||
});
|
||||
|
||||
it('shows a alert message on error', () => {
|
||||
service.updateGenericKey.mockRejectedValueOnce({});
|
||||
|
||||
createComponent();
|
||||
|
||||
return wrapper.vm.resetKey().then(() => {
|
||||
expect(wrapper.find(GlAlert).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('activate toggle', () => {
|
||||
it('triggers toggleActivated method', () => {
|
||||
const toggleService = jest.fn();
|
||||
const methods = { toggleService };
|
||||
createComponent({ methods });
|
||||
|
||||
wrapper.find(ToggleButton).vm.$emit('change', true);
|
||||
expect(toggleService).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('error is encountered', () => {
|
||||
it('restores previous value', () => {
|
||||
service.updateGenericKey.mockRejectedValueOnce({});
|
||||
createComponent();
|
||||
return wrapper.vm.resetKey().then(() => {
|
||||
expect(wrapper.find(ToggleButton).props('value')).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('prometheus is active', () => {
|
||||
beforeEach(() => {
|
||||
createComponent(
|
||||
{},
|
||||
{
|
||||
selectedIntegration: 'PROMETHEUS',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('renders a valid "select"', () => {
|
||||
expect(findSelect().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('shows the API URL input', () => {
|
||||
expect(findApiUrl().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('shows the correct default API URL', () => {
|
||||
expect(findUrl().attributes('value')).toBe(defaultAlertSettingsConfig.prometheus.url);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Opsgenie is active', () => {
|
||||
beforeEach(() => {
|
||||
createComponent(
|
||||
{},
|
||||
{
|
||||
selectedIntegration: 'OPSGENIE',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('shows a input for the Opsgenie target URL', () => {
|
||||
expect(findApiUrl().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('trigger test alert', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({});
|
||||
});
|
||||
|
||||
it('should enable the JSON input', () => {
|
||||
expect(findJsonInput().exists()).toBe(true);
|
||||
expect(findJsonInput().props('value')).toBe(null);
|
||||
});
|
||||
|
||||
it('should validate JSON input', async () => {
|
||||
createComponent(true, {
|
||||
testAlertJson: '{ "value": "test" }',
|
||||
});
|
||||
|
||||
findJsonInput().vm.$emit('change');
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(findJsonInput().attributes('state')).toBe('true');
|
||||
});
|
||||
|
||||
describe('alert service is toggled', () => {
|
||||
describe('error handling', () => {
|
||||
const toggleService = true;
|
||||
|
||||
it('should show generic error', async () => {
|
||||
service.updateGenericActive.mockRejectedValueOnce({});
|
||||
|
||||
createComponent();
|
||||
|
||||
await wrapper.vm.toggleActivated(toggleService);
|
||||
expect(wrapper.vm.active).toBe(false);
|
||||
expect(wrapper.find(GlAlert).attributes('variant')).toBe('danger');
|
||||
expect(wrapper.find(GlAlert).text()).toBe(i18n.errorMsg);
|
||||
});
|
||||
|
||||
it('should show first field specific error when available', async () => {
|
||||
const err1 = "can't be blank";
|
||||
const err2 = 'is not a valid URL';
|
||||
const key = 'api_url';
|
||||
service.updateGenericActive.mockRejectedValueOnce({
|
||||
response: { data: { errors: { [key]: [err1, err2] } } },
|
||||
});
|
||||
|
||||
createComponent();
|
||||
|
||||
await wrapper.vm.toggleActivated(toggleService);
|
||||
|
||||
expect(wrapper.find(GlAlert).text()).toContain(i18n.errorMsg);
|
||||
expect(wrapper.find(GlAlert).text()).toContain(`${key} ${err1}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -5,7 +5,6 @@ import waitForPromises from 'helpers/wait_for_promises';
|
|||
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
|
||||
import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
|
||||
import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
|
||||
import AlertsSettingsFormOld from '~/alerts_settings/components/alerts_settings_form_old.vue';
|
||||
import AlertsSettingsFormNew from '~/alerts_settings/components/alerts_settings_form_new.vue';
|
||||
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
|
||||
import getIntegrationsQuery from '~/alerts_settings/graphql/queries/get_integrations.query.graphql';
|
||||
|
@ -75,7 +74,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
},
|
||||
provide: {
|
||||
...defaultAlertSettingsConfig,
|
||||
glFeatures: { httpIntegrationsList: false },
|
||||
...provide,
|
||||
},
|
||||
mocks: {
|
||||
|
@ -110,7 +108,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
apolloProvider: fakeApollo,
|
||||
provide: {
|
||||
...defaultAlertSettingsConfig,
|
||||
glFeatures: { httpIntegrationsList: true },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -122,27 +119,16 @@ describe('AlertsSettingsWrapper', () => {
|
|||
}
|
||||
});
|
||||
|
||||
describe('with httpIntegrationsList feature flag disabled', () => {
|
||||
it('renders data driven alerts integrations list and old form by default', () => {
|
||||
describe('rendered via default permissions', () => {
|
||||
it('renders the GraphQL alerts integrations list and new form', () => {
|
||||
createComponent();
|
||||
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
|
||||
expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(true);
|
||||
expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with httpIntegrationsList feature flag enabled', () => {
|
||||
it('renders the GraphQL alerts integrations list and new form', () => {
|
||||
createComponent({ provide: { glFeatures: { httpIntegrationsList: true } } });
|
||||
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
|
||||
expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(false);
|
||||
expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('uses a loading state inside the IntegrationsList table', () => {
|
||||
createComponent({
|
||||
data: { integrations: {} },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: true,
|
||||
});
|
||||
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
|
||||
|
@ -152,7 +138,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('renders the IntegrationsList table using the API data', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
expect(findLoader().exists()).toBe(false);
|
||||
|
@ -162,7 +147,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -185,7 +169,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('calls `$apollo.mutate` with `updateHttpIntegrationMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -206,7 +189,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('calls `$apollo.mutate` with `resetHttpTokenMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -229,7 +211,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('calls `$apollo.mutate` with `createPrometheusIntegrationMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -252,7 +233,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('calls `$apollo.mutate` with `updatePrometheusIntegrationMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -273,7 +253,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('calls `$apollo.mutate` with `resetPrometheusTokenMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -296,7 +275,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('shows an error alert when integration creation fails ', async () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -311,7 +289,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('shows an error alert when integration token reset fails ', async () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -326,7 +303,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('shows an error alert when integration update fails ', async () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -341,7 +317,6 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it('shows an error alert when integration test payload fails ', async () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
@ -405,7 +380,7 @@ describe('AlertsSettingsWrapper', () => {
|
|||
it.each([true, false])('it shows/hides the alert when opsgenie is %s', active => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true }, opsgenie: { active } },
|
||||
provide: { opsgenie: { active } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
|
|
|
@ -4,11 +4,8 @@ import Vuex from 'vuex';
|
|||
import { GlAlert } from '@gitlab/ui';
|
||||
import App from '~/groups/members/components/app.vue';
|
||||
import * as commonUtils from '~/lib/utils/common_utils';
|
||||
import {
|
||||
RECEIVE_MEMBER_ROLE_ERROR,
|
||||
HIDE_ERROR,
|
||||
} from '~/vuex_shared/modules/members/mutation_types';
|
||||
import mutations from '~/vuex_shared/modules/members/mutations';
|
||||
import { RECEIVE_MEMBER_ROLE_ERROR, HIDE_ERROR } from '~/members/store/mutation_types';
|
||||
import mutations from '~/members/store/mutations';
|
||||
|
||||
describe('GroupMembersApp', () => {
|
||||
const localVue = createLocalVue();
|
||||
|
|
|
@ -220,6 +220,7 @@ describe('common_utils', () => {
|
|||
beforeEach(() => {
|
||||
elem = document.createElement('div');
|
||||
window.innerHeight = windowHeight;
|
||||
window.mrTabs = { currentAction: 'show' };
|
||||
jest.spyOn($.fn, 'animate');
|
||||
jest.spyOn($.fn, 'offset').mockReturnValue({ top: elemTop });
|
||||
});
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import AccessRequestActionButtons from '~/vue_shared/components/members/action_buttons/access_request_action_buttons.vue';
|
||||
import RemoveMemberButton from '~/vue_shared/components/members/action_buttons/remove_member_button.vue';
|
||||
import ApproveAccessRequestButton from '~/vue_shared/components/members/action_buttons/approve_access_request_button.vue';
|
||||
import { accessRequest as member } from '../mock_data';
|
||||
import AccessRequestActionButtons from '~/members/components/action_buttons/access_request_action_buttons.vue';
|
||||
import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
|
||||
import ApproveAccessRequestButton from '~/members/components/action_buttons/approve_access_request_button.vue';
|
||||
import { accessRequest as member } from '../../mock_data';
|
||||
|
||||
describe('AccessRequestActionButtons', () => {
|
||||
let wrapper;
|
|
@ -2,7 +2,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
|
|||
import Vuex from 'vuex';
|
||||
import { GlButton, GlForm } from '@gitlab/ui';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import ApproveAccessRequestButton from '~/vue_shared/components/members/action_buttons/approve_access_request_button.vue';
|
||||
import ApproveAccessRequestButton from '~/members/components/action_buttons/approve_access_request_button.vue';
|
||||
|
||||
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import InviteActionButtons from '~/vue_shared/components/members/action_buttons/invite_action_buttons.vue';
|
||||
import RemoveMemberButton from '~/vue_shared/components/members/action_buttons/remove_member_button.vue';
|
||||
import ResendInviteButton from '~/vue_shared/components/members/action_buttons/resend_invite_button.vue';
|
||||
import { invite as member } from '../mock_data';
|
||||
import InviteActionButtons from '~/members/components/action_buttons/invite_action_buttons.vue';
|
||||
import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
|
||||
import ResendInviteButton from '~/members/components/action_buttons/resend_invite_button.vue';
|
||||
import { invite as member } from '../../mock_data';
|
||||
|
||||
describe('InviteActionButtons', () => {
|
||||
let wrapper;
|
|
@ -1,10 +1,10 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import LeaveButton from '~/vue_shared/components/members/action_buttons/leave_button.vue';
|
||||
import LeaveModal from '~/vue_shared/components/members/modals/leave_modal.vue';
|
||||
import { LEAVE_MODAL_ID } from '~/vue_shared/components/members/constants';
|
||||
import { member } from '../mock_data';
|
||||
import LeaveButton from '~/members/components/action_buttons/leave_button.vue';
|
||||
import LeaveModal from '~/members/components/modals/leave_modal.vue';
|
||||
import { LEAVE_MODAL_ID } from '~/members/constants';
|
||||
import { member } from '../../mock_data';
|
||||
|
||||
describe('LeaveButton', () => {
|
||||
let wrapper;
|
|
@ -2,8 +2,8 @@ import { mount, createLocalVue } from '@vue/test-utils';
|
|||
import Vuex from 'vuex';
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import RemoveGroupLinkButton from '~/vue_shared/components/members/action_buttons/remove_group_link_button.vue';
|
||||
import { group } from '../mock_data';
|
||||
import RemoveGroupLinkButton from '~/members/components/action_buttons/remove_group_link_button.vue';
|
||||
import { group } from '../../mock_data';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
|
@ -1,7 +1,7 @@
|
|||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import Vuex from 'vuex';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import RemoveMemberButton from '~/vue_shared/components/members/action_buttons/remove_member_button.vue';
|
||||
import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
|
@ -2,7 +2,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
|
|||
import Vuex from 'vuex';
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import ResendInviteButton from '~/vue_shared/components/members/action_buttons/resend_invite_button.vue';
|
||||
import ResendInviteButton from '~/members/components/action_buttons/resend_invite_button.vue';
|
||||
|
||||
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import UserActionButtons from '~/vue_shared/components/members/action_buttons/user_action_buttons.vue';
|
||||
import RemoveMemberButton from '~/vue_shared/components/members/action_buttons/remove_member_button.vue';
|
||||
import LeaveButton from '~/vue_shared/components/members/action_buttons/leave_button.vue';
|
||||
import { member, orphanedMember } from '../mock_data';
|
||||
import UserActionButtons from '~/members/components/action_buttons/user_action_buttons.vue';
|
||||
import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
|
||||
import LeaveButton from '~/members/components/action_buttons/leave_button.vue';
|
||||
import { member, orphanedMember } from '../../mock_data';
|
||||
|
||||
describe('UserActionButtons', () => {
|
||||
let wrapper;
|
|
@ -1,8 +1,8 @@
|
|||
import { mount, createWrapper } from '@vue/test-utils';
|
||||
import { getByText as getByTextHelper } from '@testing-library/dom';
|
||||
import { GlAvatarLink } from '@gitlab/ui';
|
||||
import { group as member } from '../mock_data';
|
||||
import GroupAvatar from '~/vue_shared/components/members/avatars/group_avatar.vue';
|
||||
import { group as member } from '../../mock_data';
|
||||
import GroupAvatar from '~/members/components/avatars/group_avatar.vue';
|
||||
|
||||
describe('MemberList', () => {
|
||||
let wrapper;
|
|
@ -1,7 +1,7 @@
|
|||
import { mount, createWrapper } from '@vue/test-utils';
|
||||
import { getByText as getByTextHelper } from '@testing-library/dom';
|
||||
import { invite as member } from '../mock_data';
|
||||
import InviteAvatar from '~/vue_shared/components/members/avatars/invite_avatar.vue';
|
||||
import { invite as member } from '../../mock_data';
|
||||
import InviteAvatar from '~/members/components/avatars/invite_avatar.vue';
|
||||
|
||||
describe('MemberList', () => {
|
||||
let wrapper;
|
|
@ -1,8 +1,8 @@
|
|||
import { mount, createWrapper } from '@vue/test-utils';
|
||||
import { within } from '@testing-library/dom';
|
||||
import { GlAvatarLink, GlBadge } from '@gitlab/ui';
|
||||
import { member as memberMock, orphanedMember } from '../mock_data';
|
||||
import UserAvatar from '~/vue_shared/components/members/avatars/user_avatar.vue';
|
||||
import { member as memberMock, orphanedMember } from '../../mock_data';
|
||||
import UserAvatar from '~/members/components/avatars/user_avatar.vue';
|
||||
|
||||
describe('UserAvatar', () => {
|
||||
let wrapper;
|
|
@ -3,9 +3,9 @@ import { GlModal, GlForm } from '@gitlab/ui';
|
|||
import { nextTick } from 'vue';
|
||||
import { within } from '@testing-library/dom';
|
||||
import Vuex from 'vuex';
|
||||
import LeaveModal from '~/vue_shared/components/members/modals/leave_modal.vue';
|
||||
import { LEAVE_MODAL_ID } from '~/vue_shared/components/members/constants';
|
||||
import { member } from '../mock_data';
|
||||
import LeaveModal from '~/members/components/modals/leave_modal.vue';
|
||||
import { LEAVE_MODAL_ID } from '~/members/constants';
|
||||
import { member } from '../../mock_data';
|
||||
|
||||
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
|
||||
|
|
@ -3,9 +3,9 @@ import { GlModal, GlForm } from '@gitlab/ui';
|
|||
import { nextTick } from 'vue';
|
||||
import { within } from '@testing-library/dom';
|
||||
import Vuex from 'vuex';
|
||||
import RemoveGroupLinkModal from '~/vue_shared/components/members/modals/remove_group_link_modal.vue';
|
||||
import { REMOVE_GROUP_LINK_MODAL_ID } from '~/vue_shared/components/members/constants';
|
||||
import { group } from '../mock_data';
|
||||
import RemoveGroupLinkModal from '~/members/components/modals/remove_group_link_modal.vue';
|
||||
import { REMOVE_GROUP_LINK_MODAL_ID } from '~/members/constants';
|
||||
import { group } from '../../mock_data';
|
||||
|
||||
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { mount, createWrapper } from '@vue/test-utils';
|
||||
import { within } from '@testing-library/dom';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import CreatedAt from '~/vue_shared/components/members/table/created_at.vue';
|
||||
import CreatedAt from '~/members/components/table/created_at.vue';
|
||||
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
|
||||
describe('CreatedAt', () => {
|
|
@ -4,8 +4,8 @@ import { nextTick } from 'vue';
|
|||
import { GlDatepicker } from '@gitlab/ui';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import ExpirationDatepicker from '~/vue_shared/components/members/table/expiration_datepicker.vue';
|
||||
import { member } from '../mock_data';
|
||||
import ExpirationDatepicker from '~/members/components/table/expiration_datepicker.vue';
|
||||
import { member } from '../../mock_data';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
|
@ -2,7 +2,7 @@ import { mount, createWrapper } from '@vue/test-utils';
|
|||
import { within } from '@testing-library/dom';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import ExpiresAt from '~/vue_shared/components/members/table/expires_at.vue';
|
||||
import ExpiresAt from '~/members/components/table/expires_at.vue';
|
||||
|
||||
describe('ExpiresAt', () => {
|
||||
// March 15th, 2020
|
|
@ -1,11 +1,11 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { MEMBER_TYPES } from '~/vue_shared/components/members/constants';
|
||||
import { member as memberMock, group, invite, accessRequest } from '../mock_data';
|
||||
import MemberActionButtons from '~/vue_shared/components/members/table/member_action_buttons.vue';
|
||||
import UserActionButtons from '~/vue_shared/components/members/action_buttons/user_action_buttons.vue';
|
||||
import GroupActionButtons from '~/vue_shared/components/members/action_buttons/group_action_buttons.vue';
|
||||
import InviteActionButtons from '~/vue_shared/components/members/action_buttons/invite_action_buttons.vue';
|
||||
import AccessRequestActionButtons from '~/vue_shared/components/members/action_buttons/access_request_action_buttons.vue';
|
||||
import { MEMBER_TYPES } from '~/members/constants';
|
||||
import { member as memberMock, group, invite, accessRequest } from '../../mock_data';
|
||||
import MemberActionButtons from '~/members/components/table/member_action_buttons.vue';
|
||||
import UserActionButtons from '~/members/components/action_buttons/user_action_buttons.vue';
|
||||
import GroupActionButtons from '~/members/components/action_buttons/group_action_buttons.vue';
|
||||
import InviteActionButtons from '~/members/components/action_buttons/invite_action_buttons.vue';
|
||||
import AccessRequestActionButtons from '~/members/components/action_buttons/access_request_action_buttons.vue';
|
||||
|
||||
describe('MemberActionButtons', () => {
|
||||
let wrapper;
|
|
@ -1,10 +1,10 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { MEMBER_TYPES } from '~/vue_shared/components/members/constants';
|
||||
import { member as memberMock, group, invite, accessRequest } from '../mock_data';
|
||||
import MemberAvatar from '~/vue_shared/components/members/table/member_avatar.vue';
|
||||
import UserAvatar from '~/vue_shared/components/members/avatars/user_avatar.vue';
|
||||
import GroupAvatar from '~/vue_shared/components/members/avatars/group_avatar.vue';
|
||||
import InviteAvatar from '~/vue_shared/components/members/avatars/invite_avatar.vue';
|
||||
import { MEMBER_TYPES } from '~/members/constants';
|
||||
import { member as memberMock, group, invite, accessRequest } from '../../mock_data';
|
||||
import MemberAvatar from '~/members/components/table/member_avatar.vue';
|
||||
import UserAvatar from '~/members/components/avatars/user_avatar.vue';
|
||||
import GroupAvatar from '~/members/components/avatars/group_avatar.vue';
|
||||
import InviteAvatar from '~/members/components/avatars/invite_avatar.vue';
|
||||
|
||||
describe('MemberList', () => {
|
||||
let wrapper;
|
|
@ -1,7 +1,7 @@
|
|||
import { mount, createWrapper } from '@vue/test-utils';
|
||||
import { getByText as getByTextHelper } from '@testing-library/dom';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import MemberSource from '~/vue_shared/components/members/table/member_source.vue';
|
||||
import MemberSource from '~/members/components/table/member_source.vue';
|
||||
|
||||
describe('MemberSource', () => {
|
||||
let wrapper;
|
|
@ -1,10 +1,10 @@
|
|||
import { mount, createLocalVue } from '@vue/test-utils';
|
||||
import Vuex from 'vuex';
|
||||
import { MEMBER_TYPES } from '~/vue_shared/components/members/constants';
|
||||
import { member as memberMock, group, invite, accessRequest } from '../mock_data';
|
||||
import MembersTableCell from '~/vue_shared/components/members/table/members_table_cell.vue';
|
||||
import { MEMBER_TYPES } from '~/members/constants';
|
||||
import { member as memberMock, group, invite, accessRequest } from '../../mock_data';
|
||||
import MembersTableCell from '~/members/components/table/members_table_cell.vue';
|
||||
|
||||
describe('MemberList', () => {
|
||||
describe('MembersTableCell', () => {
|
||||
const WrappedComponent = {
|
||||
props: {
|
||||
memberType: {
|
|
@ -6,21 +6,21 @@ import {
|
|||
within,
|
||||
} from '@testing-library/dom';
|
||||
import { GlBadge, GlTable } from '@gitlab/ui';
|
||||
import MembersTable from '~/vue_shared/components/members/table/members_table.vue';
|
||||
import MemberAvatar from '~/vue_shared/components/members/table/member_avatar.vue';
|
||||
import MemberSource from '~/vue_shared/components/members/table/member_source.vue';
|
||||
import ExpiresAt from '~/vue_shared/components/members/table/expires_at.vue';
|
||||
import CreatedAt from '~/vue_shared/components/members/table/created_at.vue';
|
||||
import RoleDropdown from '~/vue_shared/components/members/table/role_dropdown.vue';
|
||||
import ExpirationDatepicker from '~/vue_shared/components/members/table/expiration_datepicker.vue';
|
||||
import MemberActionButtons from '~/vue_shared/components/members/table/member_action_buttons.vue';
|
||||
import MembersTable from '~/members/components/table/members_table.vue';
|
||||
import MemberAvatar from '~/members/components/table/member_avatar.vue';
|
||||
import MemberSource from '~/members/components/table/member_source.vue';
|
||||
import ExpiresAt from '~/members/components/table/expires_at.vue';
|
||||
import CreatedAt from '~/members/components/table/created_at.vue';
|
||||
import RoleDropdown from '~/members/components/table/role_dropdown.vue';
|
||||
import ExpirationDatepicker from '~/members/components/table/expiration_datepicker.vue';
|
||||
import MemberActionButtons from '~/members/components/table/member_action_buttons.vue';
|
||||
import * as initUserPopovers from '~/user_popovers';
|
||||
import { member as memberMock, invite, accessRequest } from '../mock_data';
|
||||
import { member as memberMock, invite, accessRequest } from '../../mock_data';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
describe('MemberList', () => {
|
||||
describe('MembersTable', () => {
|
||||
let wrapper;
|
||||
|
||||
const createStore = (state = {}) => {
|
|
@ -5,8 +5,8 @@ import { within } from '@testing-library/dom';
|
|||
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
|
||||
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import RoleDropdown from '~/vue_shared/components/members/table/role_dropdown.vue';
|
||||
import { member } from '../mock_data';
|
||||
import RoleDropdown from '~/members/components/table/role_dropdown.vue';
|
||||
import { member } from '../../mock_data';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
|
@ -1,17 +1,17 @@
|
|||
import { noop } from 'lodash';
|
||||
import axios from 'axios';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { members, group } from 'jest/vue_shared/components/members/mock_data';
|
||||
import { members, group } from 'jest/members/mock_data';
|
||||
import testAction from 'helpers/vuex_action_helper';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import httpStatusCodes from '~/lib/utils/http_status';
|
||||
import * as types from '~/vuex_shared/modules/members/mutation_types';
|
||||
import * as types from '~/members/store/mutation_types';
|
||||
import {
|
||||
updateMemberRole,
|
||||
showRemoveGroupLinkModal,
|
||||
hideRemoveGroupLinkModal,
|
||||
updateMemberExpiration,
|
||||
} from '~/vuex_shared/modules/members/actions';
|
||||
} from '~/members/store/actions';
|
||||
|
||||
describe('Vuex members actions', () => {
|
||||
describe('update member actions', () => {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue