diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-17 15:09:28 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-17 15:09:28 +0000 |
commit | 6535cf9c79362862c31ea7d26c61541b84db18d9 (patch) | |
tree | 6d646edcf11d38e8ac23bceed1340ff8907b850d /spec/frontend/set_status_modal | |
parent | 9a8f801d7352b7965fe690a599410fb50005ce67 (diff) | |
download | gitlab-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.js | 257 | ||||
-rw-r--r-- | spec/frontend/set_status_modal/user_availability_status_spec.js | 31 |
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(''); + }); + }); +}); |