2020-11-17 15:09:28 +00:00
|
|
|
import { GlModal, GlFormCheckbox } from '@gitlab/ui';
|
2021-02-14 18:09:20 +00:00
|
|
|
import { shallowMount } from '@vue/test-utils';
|
2020-11-17 15:09:28 +00:00
|
|
|
import { initEmojiMock } from 'helpers/emoji';
|
2021-01-14 15:10:46 +00:00
|
|
|
import * as UserApi from '~/api/user_api';
|
2020-11-17 15:09:28 +00:00
|
|
|
import { deprecatedCreateFlash as createFlash } from '~/flash';
|
|
|
|
import SetStatusModalWrapper, {
|
|
|
|
AVAILABILITY_STATUS,
|
|
|
|
} from '~/set_status_modal/set_status_modal_wrapper.vue';
|
|
|
|
|
|
|
|
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);
|
2020-12-24 00:10:25 +00:00
|
|
|
const findFormField = (field) => wrapper.find(`[name="user[status][${field}]"]`);
|
2020-11-17 15:09:28 +00:00
|
|
|
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(() => {
|
2021-01-14 15:10:46 +00:00
|
|
|
jest.spyOn(UserApi, 'updateUserStatus').mockResolvedValue();
|
2020-11-17 15:09:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
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 };
|
|
|
|
|
2021-01-14 15:10:46 +00:00
|
|
|
expect(UserApi.updateUserStatus).toHaveBeenCalledTimes(2);
|
|
|
|
expect(UserApi.updateUserStatus).toHaveBeenNthCalledWith(1, {
|
2020-11-17 15:09:28 +00:00
|
|
|
availability: AVAILABILITY_STATUS.NOT_SET,
|
|
|
|
...commonParams,
|
|
|
|
});
|
2021-01-14 15:10:46 +00:00
|
|
|
expect(UserApi.updateUserStatus).toHaveBeenNthCalledWith(2, {
|
2020-11-17 15:09:28 +00:00
|
|
|
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: '' });
|
2021-01-14 15:10:46 +00:00
|
|
|
jest.spyOn(UserApi, 'updateUserStatus').mockResolvedValue();
|
2020-11-17 15:09:28 +00:00
|
|
|
return initModal({ mockOnUpdateSuccess: false });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays a toast success message', async () => {
|
|
|
|
findModal().vm.$emit('ok');
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
|
2021-01-14 06:11:16 +00:00
|
|
|
expect($toast.show).toHaveBeenCalledWith('Status updated');
|
2020-11-17 15:09:28 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('with errors', () => {
|
|
|
|
beforeEach(() => {
|
2021-01-14 15:10:46 +00:00
|
|
|
jest.spyOn(UserApi, 'updateUserStatus').mockRejectedValue();
|
2020-11-17 15:09:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
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: '' });
|
2021-01-14 15:10:46 +00:00
|
|
|
jest.spyOn(UserApi, 'updateUserStatus').mockRejectedValue();
|
2020-11-17 15:09:28 +00:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|