From cb09086128f2923126d009a88b478ff3919c8309 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 8 Dec 2021 09:13:01 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- GITALY_SERVER_VERSION | 2 +- .../components/ci_variable_modal.vue | 42 ++++++++- .../javascripts/ci_variable_list/constants.js | 3 + app/views/search/results/_issuable.html.haml | 2 +- lib/gitlab/email/receiver.rb | 14 +-- lib/gitlab/email/service_desk_receiver.rb | 17 +--- lib/gitlab/git/repository.rb | 2 + ...ervice_desk_custom_address_envelope_to.eml | 24 +++++ .../service_desk_custom_address_reply.eml | 24 +++++ ...vice_desk_custom_address_x_envelope_to.eml | 24 +++++ .../components/ci_variable_modal_spec.js | 55 +++++++++++- .../issuable_header_warnings_spec.js | 6 +- .../diff_viewer/viewers/renamed_spec.js | 7 +- .../components/gl_modal_vuex_spec.js | 7 +- .../components/notes/placeholder_note_spec.js | 7 +- .../project_list_item_spec.js | 8 +- .../project_selector/project_selector_spec.js | 5 +- .../runner_instructions_modal_spec.js | 10 +-- .../labels_select_vue/dropdown_button_spec.js | 7 +- .../dropdown_contents_create_view_spec.js | 7 +- .../dropdown_contents_labels_view_spec.js | 7 +- .../dropdown_contents_spec.js | 7 +- .../labels_select_vue/dropdown_title_spec.js | 7 +- .../labels_select_vue/dropdown_value_spec.js | 7 +- .../labels_select_root_spec.js | 7 +- .../dropdown_contents_create_view_spec.js | 8 +- .../dropdown_contents_labels_view_spec.js | 8 +- .../vue_shared/components/user_select_spec.js | 8 +- .../components/vuex_module_provider_spec.js | 7 +- .../gl_feature_flags_plugin_spec.js | 11 ++- spec/frontend/vue_shared/translate_spec.js | 87 +++++++------------ .../email/service_desk_receiver_spec.rb | 34 +++++++- 32 files changed, 303 insertions(+), 168 deletions(-) create mode 100644 spec/fixtures/emails/service_desk_custom_address_envelope_to.eml create mode 100644 spec/fixtures/emails/service_desk_custom_address_reply.eml create mode 100644 spec/fixtures/emails/service_desk_custom_address_x_envelope_to.eml diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 969bcd28142..a0263e681f1 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -7034511c6f456177e023d7b418ceaa391deee79a +3ef55853e9e161204464868390d97d1a1577042d diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue index 8e527e2bff6..e630ce71bd3 100644 --- a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue +++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue @@ -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 = ''; + }, }, }; diff --git a/app/assets/javascripts/ci_variable_list/constants.js b/app/assets/javascripts/ci_variable_list/constants.js index 4ebbf05814b..663a912883b 100644 --- a/app/assets/javascripts/ci_variable_list/constants.js +++ b/app/assets/javascripts/ci_variable_list/constants.js @@ -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'; diff --git a/app/views/search/results/_issuable.html.haml b/app/views/search/results/_issuable.html.haml index 41058034d6f..36458a909fc 100644 --- a/app/views/search/results/_issuable.html.haml +++ b/app/views/search/results/_issuable.html.haml @@ -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 diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb index 526f1188065..5b2bbfbe66b 100644 --- a/lib/gitlab/email/receiver.rb +++ b/lib/gitlab/email/receiver.rb @@ -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 diff --git a/lib/gitlab/email/service_desk_receiver.rb b/lib/gitlab/email/service_desk_receiver.rb index 133c4ee4b45..6c6eb3b0a65 100644 --- a/lib/gitlab/email/service_desk_receiver.rb +++ b/lib/gitlab/email/service_desk_receiver.rb @@ -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 diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 5afdcc0bd4c..240a701aba9 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -160,6 +160,8 @@ module Gitlab wrapped_gitaly_errors do gitaly_repository_client.remove end + rescue NoRepository + nil end def replicate(source_repository) diff --git a/spec/fixtures/emails/service_desk_custom_address_envelope_to.eml b/spec/fixtures/emails/service_desk_custom_address_envelope_to.eml new file mode 100644 index 00000000000..ae8f3598a13 --- /dev/null +++ b/spec/fixtures/emails/service_desk_custom_address_envelope_to.eml @@ -0,0 +1,24 @@ +Envelope-To: support+project_slug-project_key@example.com +Return-Path: +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 ; Thu, 13 Jun 2013 17:03:50 -0400 +Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for ; 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 +To: support@example.com +Message-ID: +In-Reply-To: +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 diff --git a/spec/fixtures/emails/service_desk_custom_address_reply.eml b/spec/fixtures/emails/service_desk_custom_address_reply.eml new file mode 100644 index 00000000000..7ca17a32267 --- /dev/null +++ b/spec/fixtures/emails/service_desk_custom_address_reply.eml @@ -0,0 +1,24 @@ +Delivered-To: support+project_slug-project_key@example.com +Return-Path: +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 ; Thu, 13 Jun 2013 17:03:50 -0400 +Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for ; 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 +To: support@example.com +Message-ID: +In-Reply-To: +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 diff --git a/spec/fixtures/emails/service_desk_custom_address_x_envelope_to.eml b/spec/fixtures/emails/service_desk_custom_address_x_envelope_to.eml new file mode 100644 index 00000000000..1d6f362d3ce --- /dev/null +++ b/spec/fixtures/emails/service_desk_custom_address_x_envelope_to.eml @@ -0,0 +1,24 @@ +X-Envelope-To: support+project_slug-project_key@example.com +Return-Path: +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 ; Thu, 13 Jun 2013 17:03:50 -0400 +Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for ; 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 +To: support@example.com +Message-ID: +In-Reply-To: +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 diff --git a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js index 5c7404c1175..7c4ff67feb3 100644 --- a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js +++ b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js @@ -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', () => { diff --git a/spec/frontend/issuable/components/issuable_header_warnings_spec.js b/spec/frontend/issuable/components/issuable_header_warnings_spec.js index 11aaa5ca0df..c8380e42787 100644 --- a/spec/frontend/issuable/components/issuable_header_warnings_spec.js +++ b/spec/frontend/issuable/components/issuable_header_warnings_spec.js @@ -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(), diff --git a/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js b/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js index 9f433816b34..b8d3cbebe16 100644 --- a/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js +++ b/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js @@ -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, }); } diff --git a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js index 390a70792f3..b837a998cd6 100644 --- a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js +++ b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js @@ -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: { diff --git a/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js b/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js index 0f30b50da0b..55a65cfc4b3 100644 --- a/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js +++ b/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js @@ -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, }), diff --git a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js index 7fdacbe83a2..5afa017aa76 100644 --- a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js +++ b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js @@ -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, }; }); diff --git a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js index de5cee846a1..34cee10392d 100644 --- a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js +++ b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js @@ -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, diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js index 8536ffed573..e74a867ec97 100644 --- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js +++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js @@ -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, }), diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js index 59b170bfba9..c4ed975e746 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js @@ -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, }); }; diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js index c4a645082e6..1fe85637a62 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js @@ -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, }); }; diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js index e39e8794fdd..80b8edd28ba 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js @@ -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, }); }; diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js index 88557917cb5..9781d9c4de0 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js @@ -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, }); }; diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js index 726a113dbd9..110c1d1b7eb 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js @@ -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, diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js index 960ea77cb6e..f3c4839002b 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js @@ -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, }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js index bc1ec8b812b..4b0ba075eda 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js @@ -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, diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js index bf873f9162b..d8491334b5d 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js @@ -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: '', diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js index 2980409fdce..6f5a4b7e613 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js @@ -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, diff --git a/spec/frontend/vue_shared/components/user_select_spec.js b/spec/frontend/vue_shared/components/user_select_spec.js index b777ac0a0a4..8994e16e517 100644 --- a/spec/frontend/vue_shared/components/user_select_spec.js +++ b/spec/frontend/vue_shared/components/user_select_spec.js @@ -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', diff --git a/spec/frontend/vue_shared/components/vuex_module_provider_spec.js b/spec/frontend/vue_shared/components/vuex_module_provider_spec.js index ebd396bd87c..c136c2054ac 100644 --- a/spec/frontend/vue_shared/components/vuex_module_provider_spec.js +++ b/spec/frontend/vue_shared/components/vuex_module_provider_spec.js @@ -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); }); }); diff --git a/spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js b/spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js index 3fb60c254c9..7738a69a174 100644 --- a/spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js +++ b/spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js @@ -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: ``, 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: ``, mixins: [glFeatureFlagsMixin()], }; - const wrapper = shallowMount(component, { localVue }); + const wrapper = shallowMount(component); expect(wrapper.vm.glFeatures).toEqual({ aFeature: true, bFeature: false, diff --git a/spec/frontend/vue_shared/translate_spec.js b/spec/frontend/vue_shared/translate_spec.js index 42aa28a6309..30417161968 100644 --- a/spec/frontend/vue_shared/translate_spec.js +++ b/spec/frontend/vue_shared/translate_spec.js @@ -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: ` {{ __('${key}') }} `, - }, - { 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: ` {{ n__('${key}', 'plurals', 2) }} `, - }, - { 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: ` {{ n__('${key}', '%d days', 1) }} `, - }, - { localVue }, - ); + }); expect(wrapper.text()).toBe('1 singular translated'); }); it('and n > 1', () => { - const wrapper = mount( - { - template: ` + const wrapper = mount({ + template: ` {{ n__('${key}', '%d days', 2) }} `, - }, - { 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: ` {{ s__('Context', 'Foobar') }} `, - }, - { localVue }, - ); + }); expect(wrapper.text()).toBe(expectation); }); it('and using the pipe syntax', () => { - const wrapper = mount( - { - template: ` + const wrapper = mount({ + template: ` {{ s__('${key}') }} `, - }, - { 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: ` {{ __(\` multiline @@ -151,9 +132,7 @@ describe('Vue translate filter', () => { \`) }} `, - }, - { 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: ` {{ n__( \` @@ -180,9 +158,7 @@ describe('Vue translate filter', () => { ) }} `, - }, - { 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: ` {{ s__( \` @@ -205,9 +180,7 @@ describe('Vue translate filter', () => { ) }} `, - }, - { localVue }, - ); + }); expect(wrapper.text()).toBe(translation); }); diff --git a/spec/lib/gitlab/email/service_desk_receiver_spec.rb b/spec/lib/gitlab/email/service_desk_receiver_spec.rb index 6ba58ad5e93..49cbec6fffc 100644 --- a/spec/lib/gitlab/email/service_desk_receiver_spec.rb +++ b/spec/lib/gitlab/email/service_desk_receiver_spec.rb @@ -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