diff options
5 files changed, 58 insertions, 38 deletions
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js index 801cf3ed27e..dd10caecf28 100644 --- a/app/assets/javascripts/integrations/integration_settings_form.js +++ b/app/assets/javascripts/integrations/integration_settings_form.js @@ -1,4 +1,3 @@ -import $ from 'jquery'; import { delay } from 'lodash'; import { __, s__ } from '~/locale'; import toast from '~/vue_shared/plugins/global_toast'; @@ -8,13 +7,13 @@ import eventHub from './edit/event_hub'; export default class IntegrationSettingsForm { constructor(formSelector) { - this.$form = $(formSelector); + this.$form = document.querySelector(formSelector); this.formActive = false; this.vue = null; // Form Metadata - this.testEndPoint = this.$form.data('testUrl'); + this.testEndPoint = this.$form.dataset.testUrl; } init() { @@ -34,8 +33,7 @@ export default class IntegrationSettingsForm { this.saveIntegration(); }); eventHub.$on('getJiraIssueTypes', () => { - // eslint-disable-next-line no-jquery/no-serialize - this.getJiraIssueTypes(this.$form.serialize()); + this.getJiraIssueTypes(new FormData(this.$form)); }); eventHub.$emit('formInitialized'); @@ -47,11 +45,11 @@ export default class IntegrationSettingsForm { // 2) If this service can be saved // If both conditions are true, we override form submission // and save the service using provided configuration. - const formValid = this.$form.get(0).checkValidity() || this.formActive === false; + const formValid = this.$form.checkValidity() || this.formActive === false; if (formValid) { delay(() => { - this.$form.trigger('submit'); + this.$form.submit(); }, 100); } else { eventHub.$emit('validateForm'); @@ -65,9 +63,8 @@ export default class IntegrationSettingsForm { // 2) If this service can be tested // If both conditions are true, we override form submission // and test the service using provided configuration. - if (this.$form.get(0).checkValidity()) { - // eslint-disable-next-line no-jquery/no-serialize - this.testSettings(this.$form.serialize()); + if (this.$form.checkValidity()) { + this.testSettings(new FormData(this.$form)); } else { eventHub.$emit('validateForm'); this.vue.$store.dispatch('setIsTesting', false); @@ -79,9 +76,9 @@ export default class IntegrationSettingsForm { */ toggleServiceState() { if (this.formActive) { - this.$form.removeAttr('novalidate'); - } else if (!this.$form.attr('novalidate')) { - this.$form.attr('novalidate', 'novalidate'); + this.$form.removeAttribute('novalidate'); + } else if (!this.$form.getAttribute('novalidate')) { + this.$form.setAttribute('novalidate', 'novalidate'); } } diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue index d1326e96794..e36e37c649a 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue @@ -148,7 +148,8 @@ export default { methods: { handleInput: debounce(function debouncedSearch({ data }) { this.searchKey = data; - if (!this.suggestionsLoading) { + + if (!this.suggestionsLoading && !this.activeTokenValue) { this.$emit('fetch-suggestions', data); } }, DEBOUNCE_DELAY), diff --git a/db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb b/db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb index beb15e77878..bd76466d43a 100644 --- a/db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb +++ b/db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb @@ -75,13 +75,13 @@ class FinalizeTagginsBigintConversion < ActiveRecord::Migration[6.1] # Rename the index on the `bigint` column to match the new column name # (we already hold an exclusive lock, so no need to use DROP INDEX CONCURRENTLY here) - execute 'DROP INDEX index_taggings_on_taggable_id_and_taggable_type' + execute 'DROP INDEX IF EXISTS index_taggings_on_taggable_id_and_taggable_type' rename_index TABLE_NAME, 'i_taggings_on_taggable_id_convert_to_bigint_and_taggable_type', 'index_taggings_on_taggable_id_and_taggable_type' - execute 'DROP INDEX index_taggings_on_taggable_id_and_taggable_type_and_context' + execute 'DROP INDEX IF EXISTS index_taggings_on_taggable_id_and_taggable_type_and_context' rename_index TABLE_NAME, 'i_taggings_on_taggable_bigint_and_taggable_type_and_context', 'index_taggings_on_taggable_id_and_taggable_type_and_context' - execute 'DROP INDEX taggings_idx' + execute 'DROP INDEX IF EXISTS taggings_idx' rename_index TABLE_NAME, 'taggings_idx_tmp', 'taggings_idx' - execute 'DROP INDEX tmp_index_taggings_on_id_where_taggable_type_project' + execute 'DROP INDEX IF EXISTS tmp_index_taggings_on_id_where_taggable_type_project' rename_index TABLE_NAME, 'tmp_index_taggings_on_id_bigint_where_taggable_type_project', 'tmp_index_taggings_on_id_where_taggable_type_project' end end diff --git a/spec/frontend/integrations/integration_settings_form_spec.js b/spec/frontend/integrations/integration_settings_form_spec.js index cbb2ef380ba..f8f3f0fd318 100644 --- a/spec/frontend/integrations/integration_settings_form_spec.js +++ b/spec/frontend/integrations/integration_settings_form_spec.js @@ -23,7 +23,7 @@ describe('IntegrationSettingsForm', () => { it('should initialize form element refs on class object', () => { // Form Reference expect(integrationSettingsForm.$form).toBeDefined(); - expect(integrationSettingsForm.$form.prop('nodeName')).toEqual('FORM'); + expect(integrationSettingsForm.$form.nodeName).toBe('FORM'); expect(integrationSettingsForm.formActive).toBeDefined(); }); @@ -43,14 +43,14 @@ describe('IntegrationSettingsForm', () => { integrationSettingsForm.formActive = true; integrationSettingsForm.toggleServiceState(); - expect(integrationSettingsForm.$form.attr('novalidate')).not.toBeDefined(); + expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe(null); }); it('should set `novalidate` attribute to form when called with `false`', () => { integrationSettingsForm.formActive = false; integrationSettingsForm.toggleServiceState(); - expect(integrationSettingsForm.$form.attr('novalidate')).toBeDefined(); + expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBeDefined(); }); }); @@ -67,8 +67,7 @@ describe('IntegrationSettingsForm', () => { integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form'); integrationSettingsForm.init(); - // eslint-disable-next-line no-jquery/no-serialize - formData = integrationSettingsForm.$form.serialize(); + formData = new FormData(integrationSettingsForm.$form); }); afterEach(() => { @@ -145,8 +144,7 @@ describe('IntegrationSettingsForm', () => { integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form'); integrationSettingsForm.init(); - // eslint-disable-next-line no-jquery/no-serialize - formData = integrationSettingsForm.$form.serialize(); + formData = new FormData(integrationSettingsForm.$form); }); afterEach(() => { diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js index b48621f9d87..f9ce0338d2f 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js @@ -206,26 +206,50 @@ describe('BaseToken', () => { describe('events', () => { let wrapperWithNoStubs; - beforeEach(() => { - wrapperWithNoStubs = createComponent({ - stubs: { Portal: true }, - }); - }); - afterEach(() => { wrapperWithNoStubs.destroy(); }); - it('emits `fetch-suggestions` event on component after a delay when component emits `input` event', async () => { - jest.useFakeTimers(); + describe('when activeToken has been selected', () => { + beforeEach(() => { + wrapperWithNoStubs = createComponent({ + props: { + ...mockProps, + getActiveTokenValue: () => ({ title: '' }), + suggestionsLoading: true, + }, + stubs: { Portal: true }, + }); + }); + it('does not emit `fetch-suggestions` event on component after a delay when component emits `input` event', async () => { + jest.useFakeTimers(); - wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: 'foo' }); - await wrapperWithNoStubs.vm.$nextTick(); + wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: 'foo' }); + await wrapperWithNoStubs.vm.$nextTick(); - jest.runAllTimers(); + jest.runAllTimers(); - expect(wrapperWithNoStubs.emitted('fetch-suggestions')).toBeTruthy(); - expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']); + expect(wrapperWithNoStubs.emitted('fetch-suggestions')).toEqual([['']]); + }); + }); + + describe('when activeToken has not been selected', () => { + beforeEach(() => { + wrapperWithNoStubs = createComponent({ + stubs: { Portal: true }, + }); + }); + it('emits `fetch-suggestions` event on component after a delay when component emits `input` event', async () => { + jest.useFakeTimers(); + + wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: 'foo' }); + await wrapperWithNoStubs.vm.$nextTick(); + + jest.runAllTimers(); + + expect(wrapperWithNoStubs.emitted('fetch-suggestions')).toBeTruthy(); + expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']); + }); }); }); }); |