diff options
Diffstat (limited to 'spec/frontend/profile')
7 files changed, 131 insertions, 147 deletions
diff --git a/spec/frontend/profile/account/components/delete_account_modal_spec.js b/spec/frontend/profile/account/components/delete_account_modal_spec.js index 63e27473979..f1784500baf 100644 --- a/spec/frontend/profile/account/components/delete_account_modal_spec.js +++ b/spec/frontend/profile/account/components/delete_account_modal_spec.js @@ -1,8 +1,8 @@ +import { mount } from '@vue/test-utils'; +import { merge } from 'lodash'; import Vue from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; -import { merge } from 'lodash'; -import { mount } from '@vue/test-utils'; import deleteAccountModal from '~/profile/account/components/delete_account_modal.vue'; const GlModalStub = { diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js index 91c3c81ab30..8295d1d43cf 100644 --- a/spec/frontend/profile/account/components/update_username_spec.js +++ b/spec/frontend/profile/account/components/update_username_spec.js @@ -1,5 +1,5 @@ -import { shallowMount } from '@vue/test-utils'; import { GlModal } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import { TEST_HOST } from 'helpers/test_constants'; import axios from '~/lib/utils/axios_utils'; diff --git a/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap b/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap deleted file mode 100644 index 2fd1fd6a04e..00000000000 --- a/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap +++ /dev/null @@ -1,67 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`IntegrationView component should render IntegrationView properly 1`] = ` -<div - name="sourcegraph" -> - <label - class="label-bold" - > - - Foo - - </label> - - <gl-link-stub - class="has-tooltip" - href="http://foo.com/help" - title="More information" - > - <gl-icon-stub - class="vertical-align-middle" - name="question-o" - size="16" - /> - </gl-link-stub> - - <div - class="form-group form-check" - data-testid="profile-preferences-integration-form-group" - > - <input - data-testid="profile-preferences-integration-hidden-field" - name="user[foo_enabled]" - type="hidden" - value="0" - /> - - <input - class="form-check-input" - data-testid="profile-preferences-integration-checkbox" - id="user_foo_enabled" - name="user[foo_enabled]" - type="checkbox" - value="1" - /> - - <label - class="form-check-label" - for="user_foo_enabled" - > - - Enable foo - - </label> - - <gl-form-text-stub - tag="div" - textvariant="muted" - > - <integration-help-text-stub - message="Click %{linkStart}Foo%{linkEnd}!" - messageurl="http://foo.com" - /> - </gl-form-text-stub> - </div> -</div> -`; diff --git a/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap b/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap deleted file mode 100644 index 4df92cf86a5..00000000000 --- a/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap +++ /dev/null @@ -1,51 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ProfilePreferences component should render ProfilePreferences properly 1`] = ` -<div - class="row gl-mt-3 js-preferences-form" -> - <div - class="col-sm-12" - > - <hr - data-testid="profile-preferences-integrations-rule" - /> - </div> - - <div - class="col-lg-4 profile-settings-sidebar" - > - <h4 - class="gl-mt-0" - data-testid="profile-preferences-integrations-heading" - > - - Integrations - - </h4> - - <p> - - Customize integrations with third party services. - - </p> - </div> - - <div - class="col-lg-8" - > - <integration-view-stub - config="[object Object]" - helplink="http://foo.com/help" - message="Click %{linkStart}Foo%{linkEnd}!" - messageurl="http://foo.com" - /> - <integration-view-stub - config="[object Object]" - helplink="http://bar.com/help" - message="Click %{linkStart}Bar%{linkEnd}!" - messageurl="http://bar.com" - /> - </div> -</div> -`; diff --git a/spec/frontend/profile/preferences/components/integration_view_spec.js b/spec/frontend/profile/preferences/components/integration_view_spec.js index 5d55a089119..6ab0c70298c 100644 --- a/spec/frontend/profile/preferences/components/integration_view_spec.js +++ b/spec/frontend/profile/preferences/components/integration_view_spec.js @@ -1,9 +1,9 @@ +import { GlFormText } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import { GlFormText } from '@gitlab/ui'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import IntegrationView from '~/profile/preferences/components/integration_view.vue'; import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue'; -import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { integrationViews, userFields } from '../mock_data'; const viewProps = convertObjectPropsToCamelCase(integrationViews[0]); @@ -115,10 +115,4 @@ describe('IntegrationView component', () => { expect(findFormGroupLabel().text()).toBe('Enable foo'); }); - - it('should render IntegrationView properly', () => { - wrapper = createComponent(); - - expect(wrapper.element).toMatchSnapshot(); - }); }); diff --git a/spec/frontend/profile/preferences/components/profile_preferences_spec.js b/spec/frontend/profile/preferences/components/profile_preferences_spec.js index fcc27d8faaf..82c41178410 100644 --- a/spec/frontend/profile/preferences/components/profile_preferences_spec.js +++ b/spec/frontend/profile/preferences/components/profile_preferences_spec.js @@ -1,27 +1,58 @@ +import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; - -import ProfilePreferences from '~/profile/preferences/components/profile_preferences.vue'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import IntegrationView from '~/profile/preferences/components/integration_view.vue'; -import { integrationViews, userFields } from '../mock_data'; +import ProfilePreferences from '~/profile/preferences/components/profile_preferences.vue'; +import { i18n } from '~/profile/preferences/constants'; +import { integrationViews, userFields, bodyClasses } from '../mock_data'; + +const expectedUrl = '/foo'; describe('ProfilePreferences component', () => { let wrapper; const defaultProvide = { integrationViews: [], userFields, + bodyClasses, + themes: [{ id: 1, css_class: 'foo' }], + profilePreferencesPath: '/update-profile', + formEl: document.createElement('form'), }; function createComponent(options = {}) { - const { props = {}, provide = {} } = options; - return shallowMount(ProfilePreferences, { - provide: { - ...defaultProvide, - ...provide, - }, - propsData: props, - }); + const { props = {}, provide = {}, attachTo } = options; + return extendedWrapper( + shallowMount(ProfilePreferences, { + provide: { + ...defaultProvide, + ...provide, + }, + propsData: props, + attachTo, + }), + ); + } + + function findIntegrationsDivider() { + return wrapper.findByTestId('profile-preferences-integrations-rule'); + } + + function findIntegrationsHeading() { + return wrapper.findByTestId('profile-preferences-integrations-heading'); + } + + function findSubmitButton() { + return wrapper.findComponent(GlButton); } + function findFlashError() { + return document.querySelector('.flash-container .flash-text'); + } + + beforeEach(() => { + setFixtures('<div class="flash-container"></div>'); + }); + afterEach(() => { wrapper.destroy(); wrapper = null; @@ -30,8 +61,8 @@ describe('ProfilePreferences component', () => { it('should not render Integrations section', () => { wrapper = createComponent(); const views = wrapper.findAll(IntegrationView); - const divider = wrapper.find('[data-testid="profile-preferences-integrations-rule"]'); - const heading = wrapper.find('[data-testid="profile-preferences-integrations-heading"]'); + const divider = findIntegrationsDivider(); + const heading = findIntegrationsHeading(); expect(divider.exists()).toBe(false); expect(heading.exists()).toBe(false); @@ -40,8 +71,8 @@ describe('ProfilePreferences component', () => { it('should render Integration section', () => { wrapper = createComponent({ provide: { integrationViews } }); - const divider = wrapper.find('[data-testid="profile-preferences-integrations-rule"]'); - const heading = wrapper.find('[data-testid="profile-preferences-integrations-heading"]'); + const divider = findIntegrationsDivider(); + const heading = findIntegrationsHeading(); const views = wrapper.findAll(IntegrationView); expect(divider.exists()).toBe(true); @@ -49,9 +80,84 @@ describe('ProfilePreferences component', () => { expect(views).toHaveLength(integrationViews.length); }); - it('should render ProfilePreferences properly', () => { - wrapper = createComponent({ provide: { integrationViews } }); + describe('form submit', () => { + let form; - expect(wrapper.element).toMatchSnapshot(); + beforeEach(() => { + const div = document.createElement('div'); + div.classList.add('container-fluid'); + document.body.appendChild(div); + document.body.classList.add('content-wrapper'); + + form = document.createElement('form'); + form.setAttribute('url', expectedUrl); + form.setAttribute('method', 'put'); + + const input = document.createElement('input'); + input.setAttribute('name', 'user[theme_id]'); + input.setAttribute('type', 'radio'); + input.setAttribute('value', '1'); + input.setAttribute('checked', 'checked'); + form.appendChild(input); + + wrapper = createComponent({ provide: { formEl: form }, attachTo: document.body }); + + const beforeSendEvent = new CustomEvent('ajax:beforeSend'); + form.dispatchEvent(beforeSendEvent); + }); + + it('disables the submit button', async () => { + await wrapper.vm.$nextTick(); + const button = findSubmitButton(); + expect(button.props('disabled')).toBe(true); + }); + + it('success re-enables the submit button', async () => { + const successEvent = new CustomEvent('ajax:success'); + form.dispatchEvent(successEvent); + + await wrapper.vm.$nextTick(); + const button = findSubmitButton(); + expect(button.props('disabled')).toBe(false); + }); + + it('error re-enables the submit button', async () => { + const errorEvent = new CustomEvent('ajax:error'); + form.dispatchEvent(errorEvent); + + await wrapper.vm.$nextTick(); + const button = findSubmitButton(); + expect(button.props('disabled')).toBe(false); + }); + + it('displays the default success message', () => { + const successEvent = new CustomEvent('ajax:success'); + form.dispatchEvent(successEvent); + + expect(findFlashError().innerText.trim()).toEqual(i18n.defaultSuccess); + }); + + it('displays the custom success message', () => { + const message = 'foo'; + const successEvent = new CustomEvent('ajax:success', { detail: [{ message }] }); + form.dispatchEvent(successEvent); + + expect(findFlashError().innerText.trim()).toEqual(message); + }); + + it('displays the default error message', () => { + const errorEvent = new CustomEvent('ajax:error'); + form.dispatchEvent(errorEvent); + + expect(findFlashError().innerText.trim()).toEqual(i18n.defaultError); + }); + + it('displays the custom error message', () => { + const message = 'bar'; + const errorEvent = new CustomEvent('ajax:error', { detail: [{ message }] }); + form.dispatchEvent(errorEvent); + + expect(findFlashError().innerText.trim()).toEqual(message); + }); }); }); diff --git a/spec/frontend/profile/preferences/mock_data.js b/spec/frontend/profile/preferences/mock_data.js index d07d5f565dc..ce33fc79a39 100644 --- a/spec/frontend/profile/preferences/mock_data.js +++ b/spec/frontend/profile/preferences/mock_data.js @@ -16,3 +16,5 @@ export const integrationViews = [ export const userFields = { foo_enabled: true, }; + +export const bodyClasses = 'ui-light-indigo ui-light gl-dark'; |