summaryrefslogtreecommitdiff
path: root/spec/frontend/profile
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 08:27:35 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 08:27:35 +0000
commit7e9c479f7de77702622631cff2628a9c8dcbc627 (patch)
treec8f718a08e110ad7e1894510980d2155a6549197 /spec/frontend/profile
parente852b0ae16db4052c1c567d9efa4facc81146e88 (diff)
downloadgitlab-ce-7e9c479f7de77702622631cff2628a9c8dcbc627.tar.gz
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'spec/frontend/profile')
-rw-r--r--spec/frontend/profile/account/components/update_username_spec.js208
-rw-r--r--spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap67
-rw-r--r--spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap51
-rw-r--r--spec/frontend/profile/preferences/components/integration_view_spec.js124
-rw-r--r--spec/frontend/profile/preferences/components/profile_preferences_spec.js57
-rw-r--r--spec/frontend/profile/preferences/mock_data.js18
6 files changed, 402 insertions, 123 deletions
diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js
index be39a7f4d80..45e5e0f885f 100644
--- a/spec/frontend/profile/account/components/update_username_spec.js
+++ b/spec/frontend/profile/account/components/update_username_spec.js
@@ -1,173 +1,135 @@
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlModal } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
-import updateUsername from '~/profile/account/components/update_username.vue';
+import UpdateUsername from '~/profile/account/components/update_username.vue';
describe('UpdateUsername component', () => {
const rootUrl = TEST_HOST;
const actionUrl = `${TEST_HOST}/update/username`;
- const username = 'hasnoname';
- const newUsername = 'new_username';
- let Component;
- let vm;
+ const defaultProps = {
+ actionUrl,
+ rootUrl,
+ initialUsername: 'hasnoname',
+ };
+ let wrapper;
let axiosMock;
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(UpdateUsername, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ stubs: {
+ GlModal,
+ },
+ });
+ };
+
beforeEach(() => {
axiosMock = new MockAdapter(axios);
- Component = Vue.extend(updateUsername);
- vm = mountComponent(Component, {
- actionUrl,
- rootUrl,
- initialUsername: username,
- });
+ createComponent();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
axiosMock.restore();
});
const findElements = () => {
- const modalSelector = `#${vm.$options.modalId}`;
+ const modal = wrapper.find(GlModal);
return {
- input: vm.$el.querySelector(`#${vm.$options.inputId}`),
- openModalBtn: vm.$el.querySelector(`[data-target="${modalSelector}"]`),
- modal: vm.$el.querySelector(modalSelector),
- modalBody: vm.$el.querySelector(`${modalSelector} .modal-body`),
- modalHeader: vm.$el.querySelector(`${modalSelector} .modal-title`),
- confirmModalBtn: vm.$el.querySelector(`${modalSelector} .btn-warning`),
+ modal,
+ input: wrapper.find(`#${wrapper.vm.$options.inputId}`),
+ openModalBtn: wrapper.find('[data-testid="username-change-confirmation-modal"]'),
+ modalBody: modal.find('.modal-body'),
+ modalHeader: modal.find('.modal-title'),
+ confirmModalBtn: wrapper.find('.btn-warning'),
};
};
- it('has a disabled button if the username was not changed', done => {
- const { input, openModalBtn } = findElements();
- input.dispatchEvent(new Event('input'));
-
- Vue.nextTick()
- .then(() => {
- expect(vm.username).toBe(username);
- expect(vm.newUsername).toBe(username);
- expect(openModalBtn).toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
+ it('has a disabled button if the username was not changed', async () => {
+ const { openModalBtn } = findElements();
+
+ await wrapper.vm.$nextTick();
+
+ expect(openModalBtn.props('disabled')).toBe(true);
});
- it('has an enabled button which if the username was changed', done => {
+ it('has an enabled button which if the username was changed', async () => {
const { input, openModalBtn } = findElements();
- input.value = newUsername;
- input.dispatchEvent(new Event('input'));
-
- Vue.nextTick()
- .then(() => {
- expect(vm.username).toBe(username);
- expect(vm.newUsername).toBe(newUsername);
- expect(openModalBtn).not.toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
- });
- it('confirmation modal contains proper header and body', done => {
- const { modalBody, modalHeader } = findElements();
+ input.element.value = 'newUsername';
+ input.trigger('input');
- vm.newUsername = newUsername;
+ await wrapper.vm.$nextTick();
- Vue.nextTick()
- .then(() => {
- expect(modalHeader.textContent).toContain('Change username?');
- expect(modalBody.textContent).toContain(
- `You are going to change the username ${username} to ${newUsername}`,
- );
- })
- .then(done)
- .catch(done.fail);
+ expect(openModalBtn.props('disabled')).toBe(false);
});
- it('confirmation modal should escape usernames properly', done => {
- const { modalBody } = findElements();
+ describe('changing username', () => {
+ const newUsername = 'new_username';
- vm.username = '<i>Italic</i>';
- vm.newUsername = vm.username;
+ beforeEach(async () => {
+ createComponent();
+ wrapper.setData({ newUsername });
- Vue.nextTick()
- .then(() => {
- expect(modalBody.innerHTML).toContain('&lt;i&gt;Italic&lt;/i&gt;');
- expect(modalBody.innerHTML).not.toContain(vm.username);
- })
- .then(done)
- .catch(done.fail);
- });
+ await wrapper.vm.$nextTick();
+ });
- it('executes API call on confirmation button click', done => {
- const { confirmModalBtn } = findElements();
+ it('confirmation modal contains proper header and body', async () => {
+ const { modal } = findElements();
- axiosMock.onPut(actionUrl).replyOnce(() => [200, { message: 'Username changed' }]);
- jest.spyOn(axios, 'put');
+ expect(modal.attributes('title')).toBe('Change username?');
+ expect(modal.text()).toContain(
+ `You are going to change the username ${defaultProps.initialUsername} to ${newUsername}`,
+ );
+ });
- vm.newUsername = newUsername;
+ it('executes API call on confirmation button click', async () => {
+ axiosMock.onPut(actionUrl).replyOnce(() => [200, { message: 'Username changed' }]);
+ jest.spyOn(axios, 'put');
- Vue.nextTick()
- .then(() => {
- confirmModalBtn.click();
+ await wrapper.vm.onConfirm();
+ await wrapper.vm.$nextTick();
- expect(axios.put).toHaveBeenCalledWith(actionUrl, { user: { username: newUsername } });
- })
- .then(done)
- .catch(done.fail);
- });
+ expect(axios.put).toHaveBeenCalledWith(actionUrl, { user: { username: newUsername } });
+ });
- it('sets the username after a successful update', done => {
- const { input, openModalBtn } = findElements();
+ it('sets the username after a successful update', async () => {
+ const { input, openModalBtn } = findElements();
- axiosMock.onPut(actionUrl).replyOnce(() => {
- expect(input).toBeDisabled();
- expect(openModalBtn).toBeDisabled();
+ axiosMock.onPut(actionUrl).replyOnce(() => {
+ expect(input.attributes('disabled')).toBe('disabled');
+ expect(openModalBtn.props('disabled')).toBe(true);
- return [200, { message: 'Username changed' }];
+ return [200, { message: 'Username changed' }];
+ });
+
+ await wrapper.vm.onConfirm();
+ await wrapper.vm.$nextTick();
+
+ expect(input.attributes('disabled')).toBe(undefined);
+ expect(openModalBtn.props('disabled')).toBe(true);
});
- vm.newUsername = newUsername;
-
- vm.onConfirm()
- .then(() => {
- expect(vm.username).toBe(newUsername);
- expect(vm.newUsername).toBe(newUsername);
- expect(input).not.toBeDisabled();
- expect(input.value).toBe(newUsername);
- expect(openModalBtn).toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
- });
+ it('does not set the username after a erroneous update', async () => {
+ const { input, openModalBtn } = findElements();
- it('does not set the username after a erroneous update', done => {
- const { input, openModalBtn } = findElements();
+ axiosMock.onPut(actionUrl).replyOnce(() => {
+ expect(input.attributes('disabled')).toBe('disabled');
+ expect(openModalBtn.props('disabled')).toBe(true);
- axiosMock.onPut(actionUrl).replyOnce(() => {
- expect(input).toBeDisabled();
- expect(openModalBtn).toBeDisabled();
+ return [400, { message: 'Invalid username' }];
+ });
- return [400, { message: 'Invalid username' }];
+ await expect(wrapper.vm.onConfirm()).rejects.toThrow();
+ expect(input.attributes('disabled')).toBe(undefined);
+ expect(openModalBtn.props('disabled')).toBe(false);
});
-
- const invalidUsername = 'anything.git';
- vm.newUsername = invalidUsername;
-
- vm.onConfirm()
- .then(() => done.fail('Expected onConfirm to throw!'))
- .catch(() => {
- expect(vm.username).toBe(username);
- expect(vm.newUsername).toBe(invalidUsername);
- expect(input).not.toBeDisabled();
- expect(input.value).toBe(invalidUsername);
- expect(openModalBtn).not.toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
});
});
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
new file mode 100644
index 00000000000..2fd1fd6a04e
--- /dev/null
+++ b/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap
@@ -0,0 +1,67 @@
+// 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
new file mode 100644
index 00000000000..4df92cf86a5
--- /dev/null
+++ b/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap
@@ -0,0 +1,51 @@
+// 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
new file mode 100644
index 00000000000..5d55a089119
--- /dev/null
+++ b/spec/frontend/profile/preferences/components/integration_view_spec.js
@@ -0,0 +1,124 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { GlFormText } from '@gitlab/ui';
+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]);
+
+describe('IntegrationView component', () => {
+ let wrapper;
+ const defaultProps = {
+ config: {
+ title: 'Foo',
+ label: 'Enable foo',
+ formName: 'foo_enabled',
+ },
+ ...viewProps,
+ };
+
+ function createComponent(options = {}) {
+ const { props = {}, provide = {} } = options;
+ return shallowMount(IntegrationView, {
+ provide: {
+ userFields,
+ ...provide,
+ },
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ }
+
+ function findCheckbox() {
+ return wrapper.find('[data-testid="profile-preferences-integration-checkbox"]');
+ }
+ function findFormGroup() {
+ return wrapper.find('[data-testid="profile-preferences-integration-form-group"]');
+ }
+ function findHiddenField() {
+ return wrapper.find('[data-testid="profile-preferences-integration-hidden-field"]');
+ }
+ function findFormGroupLabel() {
+ return wrapper.find('[data-testid="profile-preferences-integration-form-group"] label');
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should render the title correctly', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.find('label.label-bold').text()).toBe('Foo');
+ });
+
+ it('should render the form correctly', () => {
+ wrapper = createComponent();
+
+ expect(findFormGroup().exists()).toBe(true);
+ expect(findHiddenField().exists()).toBe(true);
+ expect(findCheckbox().exists()).toBe(true);
+ expect(findCheckbox().attributes('id')).toBe('user_foo_enabled');
+ expect(findCheckbox().attributes('name')).toBe('user[foo_enabled]');
+ });
+
+ it('should have the checkbox value to be set to 1', () => {
+ wrapper = createComponent();
+
+ expect(findCheckbox().attributes('value')).toBe('1');
+ });
+
+ it('should have the hidden value to be set to 0', () => {
+ wrapper = createComponent();
+
+ expect(findHiddenField().attributes('value')).toBe('0');
+ });
+
+ it('should set the checkbox value to be true', () => {
+ wrapper = createComponent();
+
+ expect(findCheckbox().element.checked).toBe(true);
+ });
+
+ it('should set the checkbox value to be false when false is provided', () => {
+ wrapper = createComponent({
+ provide: {
+ userFields: {
+ foo_enabled: false,
+ },
+ },
+ });
+
+ expect(findCheckbox().element.checked).toBe(false);
+ });
+
+ it('should set the checkbox value to be false when not provided', () => {
+ wrapper = createComponent({ provide: { userFields: {} } });
+
+ expect(findCheckbox().element.checked).toBe(false);
+ });
+
+ it('should render the help text', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.find(GlFormText).exists()).toBe(true);
+ expect(wrapper.find(IntegrationHelpText).exists()).toBe(true);
+ });
+
+ it('should render the label correctly', () => {
+ wrapper = createComponent();
+
+ 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
new file mode 100644
index 00000000000..fcc27d8faaf
--- /dev/null
+++ b/spec/frontend/profile/preferences/components/profile_preferences_spec.js
@@ -0,0 +1,57 @@
+import { shallowMount } from '@vue/test-utils';
+
+import ProfilePreferences from '~/profile/preferences/components/profile_preferences.vue';
+import IntegrationView from '~/profile/preferences/components/integration_view.vue';
+import { integrationViews, userFields } from '../mock_data';
+
+describe('ProfilePreferences component', () => {
+ let wrapper;
+ const defaultProvide = {
+ integrationViews: [],
+ userFields,
+ };
+
+ function createComponent(options = {}) {
+ const { props = {}, provide = {} } = options;
+ return shallowMount(ProfilePreferences, {
+ provide: {
+ ...defaultProvide,
+ ...provide,
+ },
+ propsData: props,
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ 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"]');
+
+ expect(divider.exists()).toBe(false);
+ expect(heading.exists()).toBe(false);
+ expect(views).toHaveLength(0);
+ });
+
+ 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 views = wrapper.findAll(IntegrationView);
+
+ expect(divider.exists()).toBe(true);
+ expect(heading.exists()).toBe(true);
+ expect(views).toHaveLength(integrationViews.length);
+ });
+
+ it('should render ProfilePreferences properly', () => {
+ wrapper = createComponent({ provide: { integrationViews } });
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/profile/preferences/mock_data.js b/spec/frontend/profile/preferences/mock_data.js
new file mode 100644
index 00000000000..d07d5f565dc
--- /dev/null
+++ b/spec/frontend/profile/preferences/mock_data.js
@@ -0,0 +1,18 @@
+export const integrationViews = [
+ {
+ name: 'sourcegraph',
+ help_link: 'http://foo.com/help',
+ message: 'Click %{linkStart}Foo%{linkEnd}!',
+ message_url: 'http://foo.com',
+ },
+ {
+ name: 'gitpod',
+ help_link: 'http://bar.com/help',
+ message: 'Click %{linkStart}Bar%{linkEnd}!',
+ message_url: 'http://bar.com',
+ },
+];
+
+export const userFields = {
+ foo_enabled: true,
+};