gitlab-org--gitlab-foss/spec/frontend/vue_shared/components/clipboard_button_spec.js

192 lines
4.6 KiB
JavaScript

import { GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import initCopyToClipboard, {
CLIPBOARD_SUCCESS_EVENT,
CLIPBOARD_ERROR_EVENT,
I18N_ERROR_MESSAGE,
} from '~/behaviors/copy_to_clipboard';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
jest.mock('lodash/uniqueId', () => (prefix) => (prefix ? `${prefix}1` : 1));
describe('clipboard button', () => {
let wrapper;
const createWrapper = (propsData, options = {}) => {
wrapper = mount(ClipboardButton, {
propsData,
...options,
});
};
const findButton = () => wrapper.find(GlButton);
const expectConfirmationTooltip = async ({ event, message }) => {
const title = 'Copy this value';
createWrapper({
text: 'copy me',
title,
});
wrapper.vm.$root.$emit = jest.fn();
const button = findButton();
expect(button.attributes()).toMatchObject({
title,
'aria-label': title,
});
await button.trigger(event);
expect(wrapper.vm.$root.$emit).toHaveBeenCalledWith('bv::show::tooltip', 'clipboard-button-1');
expect(button.attributes()).toMatchObject({
title: message,
'aria-label': message,
});
jest.runAllTimers();
await nextTick();
expect(button.attributes()).toMatchObject({
title,
'aria-label': title,
});
expect(wrapper.vm.$root.$emit).toHaveBeenCalledWith('bv::hide::tooltip', 'clipboard-button-1');
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('without gfm', () => {
beforeEach(() => {
createWrapper({
text: 'copy me',
title: 'Copy this value',
cssClass: 'btn-danger',
});
});
it('renders a button for clipboard', () => {
expect(findButton().exists()).toBe(true);
expect(wrapper.attributes('data-clipboard-text')).toBe('copy me');
});
it('should have a tooltip with default values', () => {
expect(wrapper.attributes('title')).toBe('Copy this value');
});
it('should render provided classname', () => {
expect(wrapper.classes()).toContain('btn-danger');
});
});
describe('with gfm', () => {
it('sets data-clipboard-text with gfm', () => {
createWrapper({
text: 'copy me',
gfm: '`path/to/file`',
title: 'Copy this value',
cssClass: 'btn-danger',
});
expect(wrapper.attributes('data-clipboard-text')).toBe(
'{"text":"copy me","gfm":"`path/to/file`"}',
);
});
});
it('renders default slot as button text', () => {
createWrapper(
{
text: 'copy me',
title: 'Copy this value',
},
{
slots: {
default: 'Foo bar',
},
},
);
expect(findButton().text()).toBe('Foo bar');
});
it('re-emits button events', () => {
const onClick = jest.fn();
createWrapper(
{
text: 'copy me',
title: 'Copy this value',
},
{ listeners: { click: onClick } },
);
findButton().trigger('click');
expect(onClick).toHaveBeenCalled();
});
it('passes the category and variant props to the GlButton', () => {
const category = 'tertiary';
const variant = 'confirm';
createWrapper({ title: '', text: '', category, variant });
expect(findButton().props('category')).toBe(category);
expect(findButton().props('variant')).toBe(variant);
});
describe('confirmation tooltip', () => {
it('adds `id` and `data-clipboard-handle-tooltip` attributes to button', () => {
createWrapper({
text: 'copy me',
title: 'Copy this value',
});
expect(findButton().attributes()).toMatchObject({
id: 'clipboard-button-1',
'data-clipboard-handle-tooltip': 'false',
'aria-live': 'polite',
});
});
it('shows success tooltip after successful copy', () => {
expectConfirmationTooltip({
event: CLIPBOARD_SUCCESS_EVENT,
message: ClipboardButton.i18n.copied,
});
});
it('shows error tooltip after failed copy', () => {
expectConfirmationTooltip({ event: CLIPBOARD_ERROR_EVENT, message: I18N_ERROR_MESSAGE });
});
});
describe('integration', () => {
it('actually copies to clipboard', () => {
initCopyToClipboard();
document.execCommand = () => {};
jest.spyOn(document, 'execCommand').mockImplementation(() => true);
createWrapper(
{
text: 'copy me',
title: 'Copy this value',
},
{ attachTo: document.body },
);
findButton().trigger('click');
expect(document.execCommand).toHaveBeenCalledWith('copy');
});
});
});