2021-01-29 00:20:46 +05:30
|
|
|
import { GlModal, GlFormCheckbox } from '@gitlab/ui';
|
2021-03-11 19:13:27 +05:30
|
|
|
import { shallowMount } from '@vue/test-utils';
|
2022-04-04 11:22:00 +05:30
|
|
|
import { nextTick } from 'vue';
|
2022-01-26 12:08:38 +05:30
|
|
|
import { initEmojiMock, clearEmojiMock } from 'helpers/emoji';
|
2021-03-08 18:12:59 +05:30
|
|
|
import * as UserApi from '~/api/user_api';
|
2021-09-04 01:27:46 +05:30
|
|
|
import EmojiPicker from '~/emoji/components/picker.vue';
|
|
|
|
import createFlash from '~/flash';
|
2021-01-29 00:20:46 +05:30
|
|
|
import SetStatusModalWrapper, {
|
|
|
|
AVAILABILITY_STATUS,
|
|
|
|
} from '~/set_status_modal/set_status_modal_wrapper.vue';
|
|
|
|
|
|
|
|
jest.mock('~/flash');
|
|
|
|
|
|
|
|
describe('SetStatusModalWrapper', () => {
|
|
|
|
let wrapper;
|
|
|
|
const $toast = {
|
|
|
|
show: jest.fn(),
|
|
|
|
};
|
|
|
|
|
|
|
|
const defaultEmoji = 'speech_balloon';
|
|
|
|
const defaultMessage = "They're comin' in too fast!";
|
|
|
|
|
|
|
|
const defaultProps = {
|
|
|
|
currentEmoji: defaultEmoji,
|
|
|
|
currentMessage: defaultMessage,
|
|
|
|
defaultEmoji,
|
|
|
|
};
|
|
|
|
|
2021-09-04 01:27:46 +05:30
|
|
|
const createComponent = (props = {}, improvedEmojiPicker = false) => {
|
2021-01-29 00:20:46 +05:30
|
|
|
return shallowMount(SetStatusModalWrapper, {
|
|
|
|
propsData: {
|
|
|
|
...defaultProps,
|
|
|
|
...props,
|
|
|
|
},
|
|
|
|
mocks: {
|
|
|
|
$toast,
|
|
|
|
},
|
2021-09-04 01:27:46 +05:30
|
|
|
provide: {
|
|
|
|
glFeatures: { improvedEmojiPicker },
|
|
|
|
},
|
2021-01-29 00:20:46 +05:30
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const findModal = () => wrapper.find(GlModal);
|
2021-03-08 18:12:59 +05:30
|
|
|
const findFormField = (field) => wrapper.find(`[name="user[status][${field}]"]`);
|
2021-01-29 00:20:46 +05:30
|
|
|
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);
|
2021-04-29 21:17:54 +05:30
|
|
|
const findClearStatusAtMessage = () => wrapper.find('[data-testid="clear-status-at-message"]');
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
const initModal = async ({ mockOnUpdateSuccess = true, mockOnUpdateFailure = true } = {}) => {
|
2021-01-29 00:20:46 +05:30
|
|
|
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');
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-01-29 00:20:46 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
2022-01-26 12:08:38 +05:30
|
|
|
clearEmojiMock();
|
2021-01-29 00:20:46 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
describe('with minimum props', () => {
|
2021-04-29 21:17:54 +05:30
|
|
|
beforeEach(async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-04-29 21:17:54 +05:30
|
|
|
wrapper = createComponent();
|
|
|
|
return initModal();
|
|
|
|
});
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
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();
|
|
|
|
});
|
2021-04-29 21:17:54 +05:30
|
|
|
|
|
|
|
it('displays the clear status at dropdown', () => {
|
|
|
|
expect(wrapper.find('[data-testid="clear-status-at-dropdown"]').exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('does not display the clear status at message', () => {
|
|
|
|
expect(findClearStatusAtMessage().exists()).toBe(false);
|
|
|
|
});
|
2021-01-29 00:20:46 +05:30
|
|
|
});
|
|
|
|
|
2021-09-04 01:27:46 +05:30
|
|
|
describe('improvedEmojiPicker is true', () => {
|
2022-03-02 08:16:31 +05:30
|
|
|
const getEmojiPicker = () => wrapper.findComponent(EmojiPicker);
|
|
|
|
|
2021-09-04 01:27:46 +05:30
|
|
|
beforeEach(async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-09-04 01:27:46 +05:30
|
|
|
wrapper = createComponent({}, true);
|
|
|
|
return initModal();
|
|
|
|
});
|
|
|
|
|
2022-03-02 08:16:31 +05:30
|
|
|
it('renders emoji picker dropdown with custom positioning', () => {
|
|
|
|
expect(getEmojiPicker().props()).toMatchObject({
|
|
|
|
right: false,
|
|
|
|
boundary: 'viewport',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-09-04 01:27:46 +05:30
|
|
|
it('sets emojiTag when clicking in emoji picker', async () => {
|
2022-03-02 08:16:31 +05:30
|
|
|
await getEmojiPicker().vm.$emit('click', 'thumbsup');
|
2021-09-04 01:27:46 +05:30
|
|
|
|
|
|
|
expect(wrapper.vm.emojiTag).toContain('data-name="thumbsup"');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
describe('with no currentMessage set', () => {
|
|
|
|
beforeEach(async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-01-29 00:20:46 +05:30
|
|
|
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 () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-01-29 00:20:46 +05:30
|
|
|
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 () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-01-29 00:20:46 +05:30
|
|
|
wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
|
|
|
|
return initModal();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('shows the placeholder emoji', () => {
|
|
|
|
expect(findNoEmojiPlaceholder().isVisible()).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
describe('with currentClearStatusAfter set', () => {
|
|
|
|
beforeEach(async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-04-29 21:17:54 +05:30
|
|
|
wrapper = createComponent({ currentClearStatusAfter: '2021-01-01 00:00:00 UTC' });
|
|
|
|
return initModal();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays the clear status at message', () => {
|
|
|
|
const clearStatusAtMessage = findClearStatusAtMessage();
|
|
|
|
|
|
|
|
expect(clearStatusAtMessage.exists()).toBe(true);
|
|
|
|
expect(clearStatusAtMessage.text()).toBe('Your status resets on 2021-01-01 00:00:00 UTC.');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
describe('update status', () => {
|
|
|
|
describe('succeeds', () => {
|
2021-04-29 21:17:54 +05:30
|
|
|
beforeEach(async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-04-29 21:17:54 +05:30
|
|
|
wrapper = createComponent();
|
|
|
|
await initModal();
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
jest.spyOn(UserApi, 'updateUserStatus').mockResolvedValue();
|
2021-01-29 00:20:46 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('clicking "removeStatus" clears the emoji and message fields', async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
findModal().vm.$emit('secondary');
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
expect(findFormField('message').element.value).toBe('');
|
|
|
|
expect(findFormField('emoji').element.value).toBe('');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('clicking "setStatus" submits the user status', async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
findModal().vm.$emit('primary');
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
// set the availability status
|
|
|
|
findAvailabilityCheckbox().vm.$emit('input', true);
|
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
// set the currentClearStatusAfter to 30 minutes
|
|
|
|
wrapper.find('[data-testid="thirtyMinutes"]').vm.$emit('click');
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
findModal().vm.$emit('primary');
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
const commonParams = {
|
|
|
|
emoji: defaultEmoji,
|
|
|
|
message: defaultMessage,
|
|
|
|
};
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
expect(UserApi.updateUserStatus).toHaveBeenCalledTimes(2);
|
|
|
|
expect(UserApi.updateUserStatus).toHaveBeenNthCalledWith(1, {
|
2021-01-29 00:20:46 +05:30
|
|
|
availability: AVAILABILITY_STATUS.NOT_SET,
|
2021-04-29 21:17:54 +05:30
|
|
|
clearStatusAfter: null,
|
2021-01-29 00:20:46 +05:30
|
|
|
...commonParams,
|
|
|
|
});
|
2021-03-08 18:12:59 +05:30
|
|
|
expect(UserApi.updateUserStatus).toHaveBeenNthCalledWith(2, {
|
2021-01-29 00:20:46 +05:30
|
|
|
availability: AVAILABILITY_STATUS.BUSY,
|
2021-04-29 21:17:54 +05:30
|
|
|
clearStatusAfter: '30_minutes',
|
2021-01-29 00:20:46 +05:30
|
|
|
...commonParams,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('calls the "onUpdateSuccess" handler', async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
findModal().vm.$emit('primary');
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
expect(wrapper.vm.onUpdateSuccess).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('success message', () => {
|
|
|
|
beforeEach(async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-01-29 00:20:46 +05:30
|
|
|
wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
|
2021-03-08 18:12:59 +05:30
|
|
|
jest.spyOn(UserApi, 'updateUserStatus').mockResolvedValue();
|
2021-01-29 00:20:46 +05:30
|
|
|
return initModal({ mockOnUpdateSuccess: false });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays a toast success message', async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
findModal().vm.$emit('primary');
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
expect($toast.show).toHaveBeenCalledWith('Status updated');
|
2021-01-29 00:20:46 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('with errors', () => {
|
2021-04-29 21:17:54 +05:30
|
|
|
beforeEach(async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-04-29 21:17:54 +05:30
|
|
|
wrapper = createComponent();
|
|
|
|
await initModal();
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
jest.spyOn(UserApi, 'updateUserStatus').mockRejectedValue();
|
2021-01-29 00:20:46 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('calls the "onUpdateFail" handler', async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
findModal().vm.$emit('primary');
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
expect(wrapper.vm.onUpdateFail).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('error message', () => {
|
|
|
|
beforeEach(async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
await initEmojiMock();
|
2021-01-29 00:20:46 +05:30
|
|
|
wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
|
2021-03-08 18:12:59 +05:30
|
|
|
jest.spyOn(UserApi, 'updateUserStatus').mockRejectedValue();
|
2021-01-29 00:20:46 +05:30
|
|
|
return initModal({ mockOnUpdateFailure: false });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('flashes an error message', async () => {
|
2022-01-26 12:08:38 +05:30
|
|
|
findModal().vm.$emit('primary');
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2021-09-04 01:27:46 +05:30
|
|
|
expect(createFlash).toHaveBeenCalledWith({
|
|
|
|
message: "Sorry, we weren't able to set your status. Please try again later.",
|
|
|
|
});
|
2021-01-29 00:20:46 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|