Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-11-19 12:09:26 +00:00
parent 38de2aa494
commit fa6c2426a5
111 changed files with 504 additions and 1072 deletions

View File

@ -1 +1 @@
3aa577d5e9ad572a22966775126076ec4dce2bfb
d5024702496569b6de051046e5e295c44de94be5

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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: {

View File

@ -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>

View File

@ -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"

View File

@ -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',

View File

@ -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,

View File

@ -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 = {}) => {

View File

@ -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',

View File

@ -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: {

View File

@ -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',

View File

@ -1,6 +1,6 @@
<script>
import { GlAvatarLabeled } from '@gitlab/ui';
import { AVATAR_SIZE } from '../constants';
import { AVATAR_SIZE } from '../../constants';
export default {
name: 'InviteAvatar',

View File

@ -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 {

View File

@ -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',

View File

@ -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',

View File

@ -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',

View File

@ -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',

View File

@ -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']),

View File

@ -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',

View File

@ -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: {

View File

@ -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,
});

View File

@ -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 });
}
/**

View File

@ -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">

View File

@ -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({

View File

@ -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,
});

View File

@ -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

View File

@ -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.')

View File

@ -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}"

View File

@ -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= _('Im 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= _('Im 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= _('Im 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= _('Im 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'

View File

@ -0,0 +1,5 @@
---
title: Remove http_integrations_list feature flag
merge_request: 48030
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Replace Runner Page Title with Runners Hash
merge_request: 44854
author: Kev @KevSlashNull
type: changed

View File

@ -0,0 +1,5 @@
---
title: Scroll exactly to the top of a discussion on the MR Overview tab
merge_request: 47970
author:
type: fixed

View File

@ -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

View File

@ -0,0 +1,5 @@
---
title: Replace fa-exclamation-triangle in users select
merge_request: 48116
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Fixed editing labels on the swimlanes sidebar
merge_request: 47946
author:
type: fixed

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 "Im familiar with the basics of project management and DevOps."
msgid "Im familiar with the basics of DevOps."
msgstr ""
msgid "Im not very familiar with the basics of project management and DevOps."
msgid "Im 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"

View File

@ -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

View File

@ -282,6 +282,12 @@ RSpec.describe "Admin Runners" do
visit admin_runner_path(runner)
end
describe 'runner page breadcrumbs' do
it 'contains the current runners 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)

View File

@ -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

View File

@ -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('Im not very familiar with the basics of project management and DevOps')
is_expected.to have_content('Show me everything')
is_expected.to have_content('Im 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('Im familiar with the basics of project management and DevOps')
is_expected.to have_content('Show me more advanced stuff')
is_expected.to have_content('Im familiar with the basics of DevOps')
is_expected.to have_content('Show me advanced features')
end
it 'does not display any flash messages' do

View File

@ -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>"
`;

View File

@ -35,9 +35,6 @@ describe('AlertIntegrationsList', () => {
integrations: mockIntegrations,
...props,
},
provide: {
glFeatures: { httpIntegrationsList: true },
},
stubs: {
GlIcon: true,
GlButton: true,

View File

@ -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}`);
});
});
});
});
});

View File

@ -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,
});

View File

@ -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();

View File

@ -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 });
});

View File

@ -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;

View File

@ -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' }));

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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' }));

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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' }));

View File

@ -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' }));

View File

@ -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', () => {

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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: {

View File

@ -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 = {}) => {

View File

@ -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);

View File

@ -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