summaryrefslogtreecommitdiff
path: root/spec/frontend/set_status_modal
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-17 15:09:28 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-17 15:09:28 +0000
commit6535cf9c79362862c31ea7d26c61541b84db18d9 (patch)
tree6d646edcf11d38e8ac23bceed1340ff8907b850d /spec/frontend/set_status_modal
parent9a8f801d7352b7965fe690a599410fb50005ce67 (diff)
downloadgitlab-ce-6535cf9c79362862c31ea7d26c61541b84db18d9.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/set_status_modal')
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js257
-rw-r--r--spec/frontend/set_status_modal/user_availability_status_spec.js31
2 files changed, 288 insertions, 0 deletions
diff --git a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
new file mode 100644
index 00000000000..fad23aa05a4
--- /dev/null
+++ b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
@@ -0,0 +1,257 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlModal, GlFormCheckbox } from '@gitlab/ui';
+import { initEmojiMock } from 'helpers/emoji';
+import Api from '~/api';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import SetStatusModalWrapper, {
+ AVAILABILITY_STATUS,
+} from '~/set_status_modal/set_status_modal_wrapper.vue';
+
+jest.mock('~/api');
+jest.mock('~/flash');
+
+describe('SetStatusModalWrapper', () => {
+ let wrapper;
+ let mockEmoji;
+ const $toast = {
+ show: jest.fn(),
+ };
+
+ const defaultEmoji = 'speech_balloon';
+ const defaultMessage = "They're comin' in too fast!";
+
+ const defaultProps = {
+ currentEmoji: defaultEmoji,
+ currentMessage: defaultMessage,
+ defaultEmoji,
+ canSetUserAvailability: true,
+ };
+
+ const createComponent = (props = {}) => {
+ return shallowMount(SetStatusModalWrapper, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ mocks: {
+ $toast,
+ },
+ });
+ };
+
+ const findModal = () => wrapper.find(GlModal);
+ const findFormField = field => wrapper.find(`[name="user[status][${field}]"]`);
+ const findClearStatusButton = () => wrapper.find('.js-clear-user-status-button');
+ const findNoEmojiPlaceholder = () => wrapper.find('.js-no-emoji-placeholder');
+ const findToggleEmojiButton = () => wrapper.find('.js-toggle-emoji-menu');
+ const findAvailabilityCheckbox = () => wrapper.find(GlFormCheckbox);
+
+ const initModal = ({ mockOnUpdateSuccess = true, mockOnUpdateFailure = true } = {}) => {
+ const modal = findModal();
+ // mock internal emoji methods
+ wrapper.vm.showEmojiMenu = jest.fn();
+ wrapper.vm.hideEmojiMenu = jest.fn();
+ if (mockOnUpdateSuccess) wrapper.vm.onUpdateSuccess = jest.fn();
+ if (mockOnUpdateFailure) wrapper.vm.onUpdateFail = jest.fn();
+
+ modal.vm.$emit('shown');
+ return wrapper.vm.$nextTick();
+ };
+
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent();
+ return initModal();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mockEmoji.restore();
+ });
+
+ describe('with minimum props', () => {
+ it('sets the hidden status emoji field', () => {
+ const field = findFormField('emoji');
+ expect(field.exists()).toBe(true);
+ expect(field.element.value).toBe(defaultEmoji);
+ });
+
+ it('sets the message field', () => {
+ const field = findFormField('message');
+ expect(field.exists()).toBe(true);
+ expect(field.element.value).toBe(defaultMessage);
+ });
+
+ it('sets the availability field to false', () => {
+ const field = findAvailabilityCheckbox();
+ expect(field.exists()).toBe(true);
+ expect(field.element.checked).toBeUndefined();
+ });
+
+ it('has a clear status button', () => {
+ expect(findClearStatusButton().isVisible()).toBe(true);
+ });
+
+ it('clicking the toggle emoji button displays the emoji list', () => {
+ expect(wrapper.vm.showEmojiMenu).not.toHaveBeenCalled();
+ findToggleEmojiButton().trigger('click');
+ expect(wrapper.vm.showEmojiMenu).toHaveBeenCalled();
+ });
+ });
+
+ describe('with no currentMessage set', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentMessage: '' });
+ return initModal();
+ });
+
+ it('does not set the message field', () => {
+ expect(findFormField('message').element.value).toBe('');
+ });
+
+ it('hides the clear status button', () => {
+ expect(findClearStatusButton().isVisible()).toBe(false);
+ });
+
+ it('shows the placeholder emoji', () => {
+ expect(findNoEmojiPlaceholder().isVisible()).toBe(true);
+ });
+ });
+
+ describe('with no currentEmoji set', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentEmoji: '' });
+ return initModal();
+ });
+
+ it('does not set the hidden status emoji field', () => {
+ expect(findFormField('emoji').element.value).toBe('');
+ });
+
+ it('hides the placeholder emoji', () => {
+ expect(findNoEmojiPlaceholder().isVisible()).toBe(false);
+ });
+
+ describe('with no currentMessage set', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
+ return initModal();
+ });
+
+ it('shows the placeholder emoji', () => {
+ expect(findNoEmojiPlaceholder().isVisible()).toBe(true);
+ });
+ });
+ });
+
+ describe('update status', () => {
+ describe('succeeds', () => {
+ beforeEach(() => {
+ jest.spyOn(Api, 'postUserStatus').mockResolvedValue();
+ });
+
+ it('clicking "removeStatus" clears the emoji and message fields', async () => {
+ findModal().vm.$emit('cancel');
+ await wrapper.vm.$nextTick();
+
+ expect(findFormField('message').element.value).toBe('');
+ expect(findFormField('emoji').element.value).toBe('');
+ });
+
+ it('clicking "setStatus" submits the user status', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ // set the availability status
+ findAvailabilityCheckbox().vm.$emit('input', true);
+
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ const commonParams = { emoji: defaultEmoji, message: defaultMessage };
+
+ expect(Api.postUserStatus).toHaveBeenCalledTimes(2);
+ expect(Api.postUserStatus).toHaveBeenNthCalledWith(1, {
+ availability: AVAILABILITY_STATUS.NOT_SET,
+ ...commonParams,
+ });
+ expect(Api.postUserStatus).toHaveBeenNthCalledWith(2, {
+ availability: AVAILABILITY_STATUS.BUSY,
+ ...commonParams,
+ });
+ });
+
+ it('calls the "onUpdateSuccess" handler', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.onUpdateSuccess).toHaveBeenCalled();
+ });
+ });
+
+ describe('success message', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
+ jest.spyOn(Api, 'postUserStatus').mockResolvedValue();
+ return initModal({ mockOnUpdateSuccess: false });
+ });
+
+ it('displays a toast success message', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ expect($toast.show).toHaveBeenCalledWith('Status updated', {
+ position: 'top-center',
+ type: 'success',
+ });
+ });
+ });
+
+ describe('with errors', () => {
+ beforeEach(() => {
+ jest.spyOn(Api, 'postUserStatus').mockRejectedValue();
+ });
+
+ it('calls the "onUpdateFail" handler', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.onUpdateFail).toHaveBeenCalled();
+ });
+ });
+
+ describe('error message', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
+ jest.spyOn(Api, 'postUserStatus').mockRejectedValue();
+ return initModal({ mockOnUpdateFailure: false });
+ });
+
+ it('flashes an error message', async () => {
+ findModal().vm.$emit('ok');
+ await wrapper.vm.$nextTick();
+
+ expect(createFlash).toHaveBeenCalledWith(
+ "Sorry, we weren't able to set your status. Please try again later.",
+ );
+ });
+ });
+ });
+
+ describe('with canSetUserAvailability=false', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ canSetUserAvailability: false });
+ return initModal();
+ });
+
+ it('hides the set availability checkbox', () => {
+ expect(findAvailabilityCheckbox().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/set_status_modal/user_availability_status_spec.js b/spec/frontend/set_status_modal/user_availability_status_spec.js
new file mode 100644
index 00000000000..95ca0251ce0
--- /dev/null
+++ b/spec/frontend/set_status_modal/user_availability_status_spec.js
@@ -0,0 +1,31 @@
+import { shallowMount } from '@vue/test-utils';
+import UserAvailabilityStatus from '~/set_status_modal/components/user_availability_status.vue';
+import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
+
+describe('UserAvailabilityStatus', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ return shallowMount(UserAvailabilityStatus, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('with availability status', () => {
+ it(`set to ${AVAILABILITY_STATUS.BUSY}`, () => {
+ wrapper = createComponent({ availability: AVAILABILITY_STATUS.BUSY });
+ expect(wrapper.text()).toContain('(Busy)');
+ });
+
+ it(`set to ${AVAILABILITY_STATUS.NOT_SET}`, () => {
+ wrapper = createComponent({ availability: AVAILABILITY_STATUS.NOT_SET });
+ expect(wrapper.html()).toBe('');
+ });
+ });
+});