Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-12-08 09:13:01 +00:00
parent 99bcbec56c
commit cb09086128
32 changed files with 303 additions and 168 deletions

View File

@ -1 +1 @@
7034511c6f456177e023d7b418ceaa391deee79a
3ef55853e9e161204464868390d97d1a1577042d

View File

@ -17,6 +17,7 @@ import {
import Cookies from 'js-cookie';
import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale';
import Tracking from '~/tracking';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { mapComputed } from '~/vuex_shared/bindings';
import {
@ -25,10 +26,14 @@ import {
AWS_TIP_DISMISSED_COOKIE_NAME,
AWS_TIP_MESSAGE,
CONTAINS_VARIABLE_REFERENCE_MESSAGE,
EVENT_LABEL,
EVENT_ACTION,
} from '../constants';
import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL });
export default {
modalId: ADD_CI_VARIABLE_MODAL_ID,
tokens: awsTokens,
@ -51,10 +56,11 @@ export default {
GlModal,
GlSprintf,
},
mixins: [glFeatureFlagsMixin()],
mixins: [glFeatureFlagsMixin(), trackingMixin],
data() {
return {
isTipDismissed: Cookies.get(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
validationErrorEventProperty: '',
};
},
computed: {
@ -147,6 +153,14 @@ export default {
return this.variable.secret_value === '' || (this.tokenValidationState && this.maskedState);
},
},
watch: {
variable: {
handler() {
this.trackVariableValidationErrors();
},
deep: true,
},
},
methods: {
...mapActions([
'addVariable',
@ -179,6 +193,7 @@ export default {
this.clearModal();
this.resetSelectedEnvironment();
this.resetValidationErrorEvents();
},
updateOrAddVariable() {
if (this.variableBeingEdited) {
@ -193,6 +208,31 @@ export default {
this.setVariableProtected();
}
},
trackVariableValidationErrors() {
const property = this.getTrackingErrorProperty();
if (!this.validationErrorEventProperty && property) {
this.track(EVENT_ACTION, { property });
this.validationErrorEventProperty = property;
}
},
getTrackingErrorProperty() {
let property;
if (this.variable.secret_value?.length && !property) {
if (this.displayMaskedError && this.maskableRegex?.length) {
const supportedChars = this.maskableRegex.replace('^', '').replace(/{(\d,)}\$/, '');
const regex = new RegExp(supportedChars, 'g');
property = this.variable.secret_value.replace(regex, '');
}
if (this.containsVariableReference) {
property = '$';
}
}
return property;
},
resetValidationErrorEvents() {
this.validationErrorEventProperty = '';
},
},
};
</script>

View File

@ -19,6 +19,9 @@ export const AWS_TIP_MESSAGE = __(
'%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}.',
);
export const EVENT_LABEL = 'ci_variable_modal';
export const EVENT_ACTION = 'validation_error';
// AWS TOKEN CONSTANTS
export const AWS_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID';
export const AWS_DEFAULT_REGION = 'AWS_DEFAULT_REGION';

View File

@ -1,7 +1,7 @@
%div{ class: 'search-result-row gl-display-flex gl-sm-flex-direction-row gl-flex-direction-column gl-align-items-center gl-pb-3! gl-mt-5 gl-mb-0!' }
.col-sm-9
%span.gl-display-flex.gl-align-items-center
%span.badge.badge-pill.gl-badge.sm{ class: "badge-#{issuable_state_to_badge_class(issuable)}" }= issuable_state_text(issuable)
= gl_badge_tag issuable_state_text(issuable), variant: issuable_state_to_badge_class(issuable), size: :sm
= sprite_icon('eye-slash', css_class: 'gl-text-gray-500 gl-ml-2') if issuable.respond_to?(:confidential?) && issuable.confidential?
= link_to issuable_path(issuable), data: { track_action: 'click_text', track_label: "#{issuable.class.name.downcase}_title", track_property: 'search_result' }, class: 'gl-w-full' do
%span.term.str-truncated.gl-font-weight-bold.gl-ml-2= issuable.title

View File

@ -73,7 +73,7 @@ module Gitlab
def key_from_to_header
mail.to.find do |address|
key = Gitlab::IncomingEmail.key_from_address(address)
key = email_class.key_from_address(address)
break key if key
end
end
@ -100,7 +100,7 @@ module Gitlab
def find_key_from_references
ensure_references_array(mail.references).find do |mail_id|
key = Gitlab::IncomingEmail.key_from_fallback_message_id(mail_id)
key = email_class.key_from_fallback_message_id(mail_id)
break key if key
end
end
@ -119,21 +119,21 @@ module Gitlab
def find_key_from_delivered_to_header
delivered_to.find do |header|
key = Gitlab::IncomingEmail.key_from_address(header.value)
key = email_class.key_from_address(header.value)
break key if key
end
end
def find_key_from_envelope_to_header
envelope_to.find do |header|
key = Gitlab::IncomingEmail.key_from_address(header.value)
key = email_class.key_from_address(header.value)
break key if key
end
end
def find_key_from_x_envelope_to_header
x_envelope_to.find do |header|
key = Gitlab::IncomingEmail.key_from_address(header.value)
key = email_class.key_from_address(header.value)
break key if key
end
end
@ -158,6 +158,10 @@ module Gitlab
autoreply && autoreply == 'yes'
end
def email_class
Gitlab::IncomingEmail
end
end
end
end

View File

@ -6,22 +6,13 @@ module Gitlab
private
def find_handler
return unless service_desk_key
return unless mail_key
Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: service_desk_key)
Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: mail_key)
end
def service_desk_key
strong_memoize(:service_desk_key) do
find_service_desk_key
end
end
def find_service_desk_key
mail.to.find do |address|
key = ::Gitlab::ServiceDeskEmail.key_from_address(address)
break key if key
end
def email_class
::Gitlab::ServiceDeskEmail
end
end
end

View File

@ -160,6 +160,8 @@ module Gitlab
wrapped_gitaly_errors do
gitaly_repository_client.remove
end
rescue NoRepository
nil
end
def replicate(source_repository)

View File

@ -0,0 +1,24 @@
Envelope-To: support+project_slug-project_key@example.com
Return-Path: <alan@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <alan@adventuretime.ooo>
To: support@example.com
Message-ID: <CAH_Wr+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
In-Reply-To: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject: The message subject! @all
Mime-Version: 1.0
Content-Type: text/plain;
charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Sieve: CMU Sieve 2.2
X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
13 Jun 2013 14:03:48 -0700 (PDT)
X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
Service desk reply!
/label ~label2

View File

@ -0,0 +1,24 @@
Delivered-To: support+project_slug-project_key@example.com
Return-Path: <alan@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <alan@adventuretime.ooo>
To: support@example.com
Message-ID: <CAH_Wr+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
In-Reply-To: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject: The message subject! @all
Mime-Version: 1.0
Content-Type: text/plain;
charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Sieve: CMU Sieve 2.2
X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
13 Jun 2013 14:03:48 -0700 (PDT)
X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
Service desk reply!
/label ~label2

View File

@ -0,0 +1,24 @@
X-Envelope-To: support+project_slug-project_key@example.com
Return-Path: <alan@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <alan@adventuretime.ooo>
To: support@example.com
Message-ID: <CAH_Wr+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
In-Reply-To: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
Subject: The message subject! @all
Mime-Version: 1.0
Content-Type: text/plain;
charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Sieve: CMU Sieve 2.2
X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
13 Jun 2013 14:03:48 -0700 (PDT)
X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
Service desk reply!
/label ~label2

View File

@ -1,9 +1,10 @@
import { GlButton, GlFormInput } from '@gitlab/ui';
import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper';
import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
import CiVariableModal from '~/ci_variable_list/components/ci_variable_modal.vue';
import { AWS_ACCESS_KEY_ID } from '~/ci_variable_list/constants';
import { AWS_ACCESS_KEY_ID, EVENT_LABEL, EVENT_ACTION } from '~/ci_variable_list/constants';
import createStore from '~/ci_variable_list/store';
import mockData from '../services/mock_data';
import ModalStub from '../stubs';
@ -14,9 +15,12 @@ localVue.use(Vuex);
describe('Ci variable modal', () => {
let wrapper;
let store;
let trackingSpy;
const maskableRegex = '^[a-zA-Z0-9_+=/@:.~-]{8,}$';
const createComponent = (method, options = {}) => {
store = createStore({ isGroup: options.isGroup });
store = createStore({ maskableRegex, isGroup: options.isGroup });
wrapper = method(CiVariableModal, {
attachTo: document.body,
stubs: {
@ -138,6 +142,7 @@ describe('Ci variable modal', () => {
};
createComponent(mount);
store.state.variable = invalidKeyVariable;
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
it(`${rendered ? 'renders' : 'does not render'} the variable reference warning`, () => {
@ -226,6 +231,7 @@ describe('Ci variable modal', () => {
};
createComponent(mount);
store.state.variable = invalidMaskVariable;
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
it('disables the submit button', () => {
@ -235,6 +241,50 @@ describe('Ci variable modal', () => {
it('shows the correct error text', () => {
expect(findModal().text()).toContain(maskError);
});
it('sends the correct tracking event', () => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
label: EVENT_LABEL,
property: ';',
});
});
});
describe.each`
value | secret | masked | eventSent | trackingErrorProperty
${'value'} | ${'secretValue'} | ${false} | ${0} | ${null}
${'shortMasked'} | ${'short'} | ${true} | ${0} | ${null}
${'withDollar$Sign'} | ${'dollar$ign'} | ${false} | ${1} | ${'$'}
${'withDollar$Sign'} | ${'dollar$ign'} | ${true} | ${1} | ${'$'}
${'unsupported'} | ${'unsupported|char'} | ${true} | ${1} | ${'|'}
${'unsupportedMasked'} | ${'unsupported|char'} | ${false} | ${0} | ${null}
`('Adding a new variable', ({ value, secret, masked, eventSent, trackingErrorProperty }) => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const invalidKeyVariable = {
...variable,
key: 'key',
value,
secret_value: secret,
masked,
};
createComponent(mount);
store.state.variable = invalidKeyVariable;
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
it(`${
eventSent > 0 ? 'sends the correct' : 'does not send the'
} variable validation tracking event`, () => {
expect(trackingSpy).toHaveBeenCalledTimes(eventSent);
if (eventSent > 0) {
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
label: EVENT_LABEL,
property: trackingErrorProperty,
});
}
});
});
describe('when both states are valid', () => {
@ -249,7 +299,6 @@ describe('Ci variable modal', () => {
};
createComponent(mount);
store.state.variable = validMaskandKeyVariable;
store.state.maskableRegex = /^[a-zA-Z0-9_+=/@:.~-]{8,}$/;
});
it('does not disable the submit button', () => {

View File

@ -1,4 +1,4 @@
import { createLocalVue } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
@ -9,8 +9,7 @@ import IssuableHeaderWarnings from '~/issuable/components/issuable_header_warnin
const ISSUABLE_TYPE_ISSUE = 'issue';
const ISSUABLE_TYPE_MR = 'merge request';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
describe('IssuableHeaderWarnings', () => {
let wrapper;
@ -24,7 +23,6 @@ describe('IssuableHeaderWarnings', () => {
const createComponent = ({ store, provide }) => {
wrapper = shallowMountExtended(IssuableHeaderWarnings, {
store,
localVue,
provide,
directives: {
GlTooltip: createMockDirective(),

View File

@ -1,4 +1,5 @@
import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import { shallowMount, mount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import {
TRANSITION_LOAD_START,
@ -11,15 +12,13 @@ import {
} from '~/diffs/constants';
import Renamed from '~/vue_shared/components/diff_viewer/viewers/renamed.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
function createRenamedComponent({ props = {}, store = new Vuex.Store({}), deep = false }) {
const mnt = deep ? mount : shallowMount;
return mnt(Renamed, {
propsData: { ...props },
localVue,
store,
});
}

View File

@ -1,12 +1,12 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import GlModalVuex from '~/vue_shared/components/gl_modal_vuex.vue';
import createState from '~/vuex_shared/modules/modal/state';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
const TEST_SLOT = 'Lorem ipsum modal dolar sit.';
const TEST_MODAL_ID = 'my-modal-id';
@ -36,7 +36,6 @@ describe('GlModalVuex', () => {
wrapper = shallowMount(GlModalVuex, {
...options,
localVue,
store,
propsData,
stubs: {

View File

@ -1,10 +1,10 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import IssuePlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
import { userDataMock } from '../../../notes/mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
const getters = {
getUserData: () => userDataMock,
@ -17,7 +17,6 @@ describe('Issue placeholder note component', () => {
const createComponent = (isIndividual = false) => {
wrapper = shallowMount(IssuePlaceholderNote, {
localVue,
store: new Vuex.Store({
getters,
}),

View File

@ -1,13 +1,12 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import mockProjects from 'test_fixtures_static/projects.json';
import { trimText } from 'helpers/text_helper';
import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
const localVue = createLocalVue();
describe('ProjectListItem component', () => {
const Component = localVue.extend(ProjectListItem);
const Component = Vue.extend(ProjectListItem);
let wrapper;
let vm;
let options;
@ -20,7 +19,6 @@ describe('ProjectListItem component', () => {
project,
selected: false,
},
localVue,
};
});

View File

@ -1,5 +1,5 @@
import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import { mount } from '@vue/test-utils';
import { head } from 'lodash';
import Vue from 'vue';
import mockProjects from 'test_fixtures_static/projects.json';
@ -7,8 +7,6 @@ import { trimText } from 'helpers/text_helper';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
const localVue = createLocalVue();
describe('ProjectSelector component', () => {
let wrapper;
let vm;
@ -28,7 +26,6 @@ describe('ProjectSelector component', () => {
beforeEach(() => {
wrapper = mount(Vue.extend(ProjectSelector), {
localVue,
propsData: {
projectSearchResults: searchResults,
selectedProjects: selected,

View File

@ -1,7 +1,7 @@
import { GlAlert, GlModal, GlButton, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@ -16,8 +16,7 @@ import {
mockGraphqlInstructionsWindows,
} from './mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
Vue.use(VueApollo);
let resizeCallback;
const MockResizeObserver = {
@ -33,7 +32,7 @@ const MockResizeObserver = {
},
};
localVue.directive('gl-resize-observer', MockResizeObserver);
Vue.directive('gl-resize-observer', MockResizeObserver);
jest.mock('@gitlab/ui/dist/utils');
@ -67,7 +66,6 @@ describe('RunnerInstructionsModal component', () => {
registrationToken: 'MY_TOKEN',
...props,
},
localVue,
apolloProvider: fakeApollo,
...options,
}),

View File

@ -1,5 +1,6 @@
import { GlIcon, GlButton } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import DropdownButton from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue';
@ -9,8 +10,7 @@ import labelSelectModule from '~/vue_shared/components/sidebar/labels_select_vue
import { mockConfig } from './mock_data';
let store;
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
const createComponent = (initialState = mockConfig) => {
store = new Vuex.Store(labelSelectModule());
@ -18,7 +18,6 @@ const createComponent = (initialState = mockConfig) => {
store.dispatch('setInitialState', initialState);
return shallowMount(DropdownButton, {
localVue,
store,
});
};

View File

@ -1,5 +1,6 @@
import { GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue';
@ -8,8 +9,7 @@ import labelSelectModule from '~/vue_shared/components/sidebar/labels_select_vue
import { mockConfig, mockSuggestedColors } from './mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
const createComponent = (initialState = mockConfig) => {
const store = new Vuex.Store(labelSelectModule());
@ -17,7 +17,6 @@ const createComponent = (initialState = mockConfig) => {
store.dispatch('setInitialState', initialState);
return shallowMount(DropdownContentsCreateView, {
localVue,
store,
});
};

View File

@ -5,7 +5,8 @@ import {
GlSearchBoxByType,
GlLink,
} from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue';
@ -18,8 +19,7 @@ import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/stor
import { mockConfig, mockLabels, mockRegularLabel } from './mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
describe('DropdownContentsLabelsView', () => {
let wrapper;
@ -43,7 +43,6 @@ describe('DropdownContentsLabelsView', () => {
store.dispatch('receiveLabelsSuccess', mockLabels);
wrapper = shallowMount(DropdownContentsLabelsView, {
localVue,
store,
});
};

View File

@ -1,4 +1,5 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
@ -7,8 +8,7 @@ import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vu
import { mockConfig } from './mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
const createComponent = (initialState = mockConfig, propsData = {}) => {
const store = new Vuex.Store(labelsSelectModule());
@ -17,7 +17,6 @@ const createComponent = (initialState = mockConfig, propsData = {}) => {
return shallowMount(DropdownContents, {
propsData,
localVue,
store,
});
};

View File

@ -1,5 +1,6 @@
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue';
@ -8,8 +9,7 @@ import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vu
import { mockConfig } from './mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
const createComponent = (initialState = mockConfig) => {
const store = new Vuex.Store(labelsSelectModule());
@ -17,7 +17,6 @@ const createComponent = (initialState = mockConfig) => {
store.dispatch('setInitialState', initialState);
return shallowMount(DropdownTitle, {
localVue,
store,
propsData: {
labelsSelectInProgress: false,

View File

@ -1,5 +1,6 @@
import { GlLabel } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import DropdownValue from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue';
@ -8,8 +9,7 @@ import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vu
import { mockConfig, mockLabels, mockRegularLabel, mockScopedLabel } from './mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
describe('DropdownValue', () => {
let wrapper;
@ -23,7 +23,6 @@ describe('DropdownValue', () => {
store.dispatch('setInitialState', { ...mockConfig, ...initialState });
wrapper = shallowMount(DropdownValue, {
localVue,
store,
slots,
});

View File

@ -1,4 +1,5 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { isInViewport } from '~/lib/utils/common_utils';
@ -18,8 +19,7 @@ jest.mock('~/lib/utils/common_utils', () => ({
isInViewport: jest.fn().mockReturnValue(true),
}));
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
describe('LabelsSelectRoot', () => {
let wrapper;
@ -27,7 +27,6 @@ describe('LabelsSelectRoot', () => {
const createComponent = (config = mockConfig, slots = {}) => {
wrapper = shallowMount(LabelsSelectRoot, {
localVue,
slots,
store,
propsData: config,

View File

@ -1,6 +1,6 @@
import { GlLoadingIcon, GlLink } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@ -18,8 +18,7 @@ jest.mock('~/flash');
const colors = Object.keys(mockSuggestedColors);
const localVue = createLocalVue();
localVue.use(VueApollo);
Vue.use(VueApollo);
const userRecoverableError = {
...createLabelSuccessfulResponse,
@ -63,7 +62,6 @@ describe('DropdownContentsCreateView', () => {
});
wrapper = shallowMount(DropdownContentsCreateView, {
localVue,
apolloProvider: mockApollo,
propsData: {
fullPath: '',

View File

@ -4,8 +4,8 @@ import {
GlDropdownItem,
GlIntersectionObserver,
} from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@ -19,8 +19,7 @@ import { mockConfig, workspaceLabelsQueryResponse } from './mock_data';
jest.mock('~/flash');
const localVue = createLocalVue();
localVue.use(VueApollo);
Vue.use(VueApollo);
const localSelectedLabels = [
{
@ -47,7 +46,6 @@ describe('DropdownContentsLabelsView', () => {
const mockApollo = createMockApollo([[projectLabelsQuery, queryHandler]]);
wrapper = shallowMount(DropdownContentsLabelsView, {
localVue,
apolloProvider: mockApollo,
provide: {
variant: DropdownVariant.Sidebar,

View File

@ -1,7 +1,7 @@
import { GlSearchBoxByType, GlDropdown } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
import { nextTick } from 'vue';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@ -33,8 +33,7 @@ const waitForSearch = async () => {
await waitForPromises();
};
const localVue = createLocalVue();
localVue.use(VueApollo);
Vue.use(VueApollo);
describe('User select dropdown', () => {
let wrapper;
@ -62,7 +61,6 @@ describe('User select dropdown', () => {
[getIssueParticipantsQuery, participantsQueryHandler],
]);
wrapper = shallowMount(UserSelect, {
localVue,
apolloProvider: fakeApollo,
propsData: {
headerText: 'test',

View File

@ -1,4 +1,4 @@
import { mount, createLocalVue } from '@vue/test-utils';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import VuexModuleProvider from '~/vue_shared/components/vuex_module_provider.vue';
@ -38,10 +38,9 @@ describe('~/vue_shared/components/vuex_module_provider', () => {
it('does not blow up when used with vue-apollo', () => {
// See https://github.com/vuejs/vue-apollo/pull/1153 for details
const localVue = createLocalVue();
localVue.use(VueApollo);
Vue.use(VueApollo);
createComponent({ localVue });
createComponent();
expect(findProvidedVuexModule()).toBe(TEST_VUEX_MODULE);
});
});

View File

@ -1,9 +1,8 @@
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import GlFeatureFlags from '~/vue_shared/gl_feature_flags_plugin';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
const localVue = createLocalVue();
describe('GitLab Feature Flags Plugin', () => {
beforeEach(() => {
window.gon = {
@ -17,7 +16,7 @@ describe('GitLab Feature Flags Plugin', () => {
},
};
localVue.use(GlFeatureFlags);
Vue.use(GlFeatureFlags);
});
it('should provide glFeatures to components', () => {
@ -25,7 +24,7 @@ describe('GitLab Feature Flags Plugin', () => {
template: `<span></span>`,
inject: ['glFeatures'],
};
const wrapper = shallowMount(component, { localVue });
const wrapper = shallowMount(component);
expect(wrapper.vm.glFeatures).toEqual({
aFeature: true,
bFeature: false,
@ -39,7 +38,7 @@ describe('GitLab Feature Flags Plugin', () => {
template: `<span></span>`,
mixins: [glFeatureFlagsMixin()],
};
const wrapper = shallowMount(component, { localVue });
const wrapper = shallowMount(component);
expect(wrapper.vm.glFeatures).toEqual({
aFeature: true,
bFeature: false,

View File

@ -1,9 +1,9 @@
import { mount, createLocalVue } from '@vue/test-utils';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import locale from '~/locale';
import Translate from '~/vue_shared/translate';
const localVue = createLocalVue();
localVue.use(Translate);
Vue.use(Translate);
describe('Vue translate filter', () => {
const createTranslationMock = (key, ...translations) => {
@ -26,16 +26,13 @@ describe('Vue translate filter', () => {
const translation = 'singular_translated';
createTranslationMock(key, translation);
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ __('${key}') }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe(translation);
});
@ -45,16 +42,13 @@ describe('Vue translate filter', () => {
const translationPlural = 'plural_multiple translation';
createTranslationMock(key, 'plural_singular translation', translationPlural);
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ n__('${key}', 'plurals', 2) }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe(translationPlural);
});
@ -67,31 +61,25 @@ describe('Vue translate filter', () => {
});
it('and n === 1', () => {
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ n__('${key}', '%d days', 1) }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe('1 singular translated');
});
it('and n > 1', () => {
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ n__('${key}', '%d days', 2) }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe('2 plural translated');
});
@ -107,31 +95,25 @@ describe('Vue translate filter', () => {
});
it('and using two parameters', () => {
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ s__('Context', 'Foobar') }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe(expectation);
});
it('and using the pipe syntax', () => {
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ s__('${key}') }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe(expectation);
});
@ -141,9 +123,8 @@ describe('Vue translate filter', () => {
const translation = 'multiline string translated';
createTranslationMock('multiline string', translation);
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ __(\`
multiline
@ -151,9 +132,7 @@ describe('Vue translate filter', () => {
\`) }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe(translation);
});
@ -163,9 +142,8 @@ describe('Vue translate filter', () => {
createTranslationMock('multiline string', 'multiline string singular', translation);
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ n__(
\`
@ -180,9 +158,7 @@ describe('Vue translate filter', () => {
) }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe(translation);
});
@ -192,9 +168,8 @@ describe('Vue translate filter', () => {
createTranslationMock('Context| multiline string', translation);
const wrapper = mount(
{
template: `
const wrapper = mount({
template: `
<span>
{{ s__(
\`
@ -205,9 +180,7 @@ describe('Vue translate filter', () => {
) }}
</span>
`,
},
{ localVue },
);
});
expect(wrapper.text()).toBe(translation);
});

View File

@ -9,9 +9,7 @@ RSpec.describe Gitlab::Email::ServiceDeskReceiver do
context 'when the email contains a valid email address' do
before do
stub_service_desk_email_setting(enabled: true, address: 'support+%{key}@example.com')
end
it 'finds the service desk key' do
handler = double(execute: true, metrics_event: true, metrics_params: true)
expected_params = [
an_instance_of(Mail::Message), nil,
@ -20,8 +18,38 @@ RSpec.describe Gitlab::Email::ServiceDeskReceiver do
expect(Gitlab::Email::Handler::ServiceDeskHandler)
.to receive(:new).with(*expected_params).and_return(handler)
end
receiver.execute
context 'when in a To header' do
it 'finds the service desk key' do
receiver.execute
end
end
context 'when the email contains a valid email address in a header' do
context 'when in a Delivered-To header' do
let(:email) { fixture_file('emails/service_desk_custom_address_reply.eml') }
it 'finds the service desk key' do
receiver.execute
end
end
context 'when in a Envelope-To header' do
let(:email) { fixture_file('emails/service_desk_custom_address_envelope_to.eml') }
it 'finds the service desk key' do
receiver.execute
end
end
context 'when in a X-Envelope-To header' do
let(:email) { fixture_file('emails/service_desk_custom_address_x_envelope_to.eml') }
it 'finds the service desk key' do
receiver.execute
end
end
end
end