gitlab-org--gitlab-foss/spec/frontend/vue_shared/components/form/input_copy_toggle_visibilit...

293 lines
8.2 KiB
JavaScript

import { merge } from 'lodash';
import { GlFormInputGroup } from '@gitlab/ui';
import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { mountExtended } from 'helpers/vue_test_utils_helper';
describe('InputCopyToggleVisibility', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
});
const valueProp = 'hR8x1fuJbzwu5uFKLf9e';
const createComponent = (options = {}) => {
wrapper = mountExtended(
InputCopyToggleVisibility,
merge({}, options, {
directives: {
GlTooltip: createMockDirective(),
},
}),
);
};
const findFormInputGroup = () => wrapper.findComponent(GlFormInputGroup);
const findFormInput = () => findFormInputGroup().find('input');
const findRevealButton = () =>
wrapper.findByRole('button', {
name: InputCopyToggleVisibility.i18n.toggleVisibilityLabelReveal,
});
const findHideButton = () =>
wrapper.findByRole('button', {
name: InputCopyToggleVisibility.i18n.toggleVisibilityLabelHide,
});
const findCopyButton = () => wrapper.findComponent(ClipboardButton);
const createCopyEvent = () => {
const event = new Event('copy', { cancelable: true });
Object.assign(event, { preventDefault: jest.fn(), clipboardData: { setData: jest.fn() } });
return event;
};
const itDoesNotModifyCopyEvent = () => {
it('does not modify copy event', () => {
const event = createCopyEvent();
findFormInput().element.dispatchEvent(event);
expect(event.clipboardData.setData).not.toHaveBeenCalled();
expect(event.preventDefault).not.toHaveBeenCalled();
});
};
describe('when `value` prop is passed', () => {
beforeEach(() => {
createComponent({
propsData: {
value: valueProp,
},
});
});
it('displays value as hidden', () => {
expect(findFormInput().element.value).toBe('********************');
});
it('saves actual value to clipboard when manually copied', () => {
const event = createCopyEvent();
findFormInput().element.dispatchEvent(event);
expect(event.clipboardData.setData).toHaveBeenCalledWith('text/plain', valueProp);
expect(event.preventDefault).toHaveBeenCalled();
});
it('emits `copy` event when manually copied the token', () => {
expect(wrapper.emitted('copy')).toBeUndefined();
findFormInput().element.dispatchEvent(createCopyEvent());
expect(wrapper.emitted()).toHaveProperty('copy');
expect(wrapper.emitted('copy')).toHaveLength(1);
expect(wrapper.emitted('copy')[0]).toEqual([]);
});
describe('visibility toggle button', () => {
it('renders a reveal button', () => {
const revealButton = findRevealButton();
expect(revealButton.exists()).toBe(true);
const tooltip = getBinding(revealButton.element, 'gl-tooltip');
expect(tooltip.value).toBe(InputCopyToggleVisibility.i18n.toggleVisibilityLabelReveal);
});
describe('when clicked', () => {
let event;
beforeEach(async () => {
event = { stopPropagation: jest.fn() };
await findRevealButton().trigger('click', event);
});
it('displays value', () => {
expect(findFormInput().element.value).toBe(valueProp);
});
it('renders a hide button', () => {
const hideButton = findHideButton();
expect(hideButton.exists()).toBe(true);
const tooltip = getBinding(hideButton.element, 'gl-tooltip');
expect(tooltip.value).toBe(InputCopyToggleVisibility.i18n.toggleVisibilityLabelHide);
});
it('emits `visibility-change` event', () => {
expect(wrapper.emitted('visibility-change')[0]).toEqual([true]);
});
it('stops propagation on click event', () => {
// in case the input is located in a dropdown or modal
expect(event.stopPropagation).toHaveBeenCalledTimes(1);
});
});
});
describe('copy button', () => {
it('renders button with correct props passed', () => {
expect(findCopyButton().props()).toMatchObject({
text: valueProp,
title: 'Copy',
});
});
describe('when clicked', () => {
beforeEach(async () => {
await findCopyButton().trigger('click');
});
it('emits `copy` event', () => {
expect(wrapper.emitted()).toHaveProperty('copy');
expect(wrapper.emitted('copy')).toHaveLength(1);
expect(wrapper.emitted('copy')[0]).toEqual([]);
});
});
});
});
describe('when `value` prop is not passed', () => {
beforeEach(() => {
createComponent();
});
it('displays value as hidden with 20 asterisks', () => {
expect(findFormInput().element.value).toBe('********************');
});
});
describe('when `initialVisibility` prop is `true`', () => {
const label = 'My label';
beforeEach(() => {
createComponent({
propsData: {
value: valueProp,
initialVisibility: true,
label,
'label-for': 'my-input',
formInputGroupProps: {
id: 'my-input',
},
},
});
});
it('displays value', () => {
expect(findFormInput().element.value).toBe(valueProp);
});
itDoesNotModifyCopyEvent();
describe('when input is clicked', () => {
it('selects input value', async () => {
const mockSelect = jest.fn();
wrapper.vm.$refs.input.$el.select = mockSelect;
await wrapper.findByLabelText(label).trigger('click');
expect(mockSelect).toHaveBeenCalled();
});
});
describe('when label is clicked', () => {
it('selects input value', async () => {
const mockSelect = jest.fn();
wrapper.vm.$refs.input.$el.select = mockSelect;
await wrapper.find('label').trigger('click');
expect(mockSelect).toHaveBeenCalled();
});
});
});
describe('when `showToggleVisibilityButton` is `false`', () => {
beforeEach(() => {
createComponent({
propsData: {
value: valueProp,
showToggleVisibilityButton: false,
},
});
});
it('does not render visibility toggle button', () => {
expect(findRevealButton().exists()).toBe(false);
expect(findHideButton().exists()).toBe(false);
});
it('displays value', () => {
expect(findFormInput().element.value).toBe(valueProp);
});
itDoesNotModifyCopyEvent();
});
describe('when `showCopyButton` is `false`', () => {
beforeEach(() => {
createComponent({
propsData: {
showCopyButton: false,
},
});
});
it('does not render copy button', () => {
expect(findCopyButton().exists()).toBe(false);
});
});
it('passes `formInputGroupProps` prop only to the input', () => {
createComponent({
propsData: {
formInputGroupProps: {
name: 'Foo bar',
'data-qa-selector': 'Foo bar',
class: 'Foo bar',
id: 'Foo bar',
},
},
});
expect(findFormInput().attributes()).toMatchObject({
name: 'Foo bar',
'data-qa-selector': 'Foo bar',
class: expect.stringContaining('Foo bar'),
id: 'Foo bar',
});
const attributesInputGroup = findFormInputGroup().attributes();
expect(attributesInputGroup.name).toBeUndefined();
expect(attributesInputGroup['data-qa-selector']).toBeUndefined();
expect(attributesInputGroup.class).not.toContain('Foo bar');
expect(attributesInputGroup.id).toBeUndefined();
});
it('passes `copyButtonTitle` prop to `ClipboardButton`', () => {
createComponent({
propsData: {
copyButtonTitle: 'Copy token',
},
});
expect(findCopyButton().props('title')).toBe('Copy token');
});
it('renders slots in `gl-form-group`', () => {
const description = 'Mock input description';
createComponent({
slots: {
description,
},
});
expect(wrapper.findByText(description).exists()).toBe(true);
});
});