diff options
Diffstat (limited to 'spec/frontend/sidebar/components/copy')
3 files changed, 187 insertions, 0 deletions
diff --git a/spec/frontend/sidebar/components/copy/copy_email_to_clipboard_spec.js b/spec/frontend/sidebar/components/copy/copy_email_to_clipboard_spec.js new file mode 100644 index 00000000000..5b6db43a366 --- /dev/null +++ b/spec/frontend/sidebar/components/copy/copy_email_to_clipboard_spec.js @@ -0,0 +1,17 @@ +import { shallowMount } from '@vue/test-utils'; +import CopyEmailToClipboard from '~/sidebar/components/copy/copy_email_to_clipboard.vue'; +import CopyableField from '~/sidebar/components/copy/copyable_field.vue'; + +describe('CopyEmailToClipboard component', () => { + const mockIssueEmailAddress = 'sample+email@test.com'; + + const wrapper = shallowMount(CopyEmailToClipboard, { + propsData: { + issueEmailAddress: mockIssueEmailAddress, + }, + }); + + it('sets CopyableField `value` prop to issueEmailAddress', () => { + expect(wrapper.findComponent(CopyableField).props('value')).toBe(mockIssueEmailAddress); + }); +}); diff --git a/spec/frontend/sidebar/components/copy/copyable_field_spec.js b/spec/frontend/sidebar/components/copy/copyable_field_spec.js new file mode 100644 index 00000000000..7790d77bc65 --- /dev/null +++ b/spec/frontend/sidebar/components/copy/copyable_field_spec.js @@ -0,0 +1,77 @@ +import { GlLoadingIcon, GlSprintf } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; +import CopyableField from '~/sidebar/components/copy/copyable_field.vue'; + +describe('SidebarCopyableField', () => { + let wrapper; + + const defaultProps = { + value: 'Gl-1', + name: 'Reference', + }; + + const createComponent = (propsData = defaultProps) => { + wrapper = shallowMount(CopyableField, { + propsData, + stubs: { + GlSprintf, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findClipboardButton = () => wrapper.findComponent(ClipboardButton); + const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + + describe('template', () => { + describe('when `isLoading` prop is `false`', () => { + beforeEach(() => { + createComponent(); + }); + + it('renders copyable field', () => { + expect(wrapper.text()).toContain('Reference: Gl-1'); + }); + + it('renders ClipboardButton with correct props', () => { + const clipboardButton = findClipboardButton(); + + expect(clipboardButton.exists()).toBe(true); + expect(clipboardButton.props('title')).toBe(`Copy ${defaultProps.name}`); + expect(clipboardButton.props('text')).toBe(defaultProps.value); + }); + + it('does not render loading icon', () => { + expect(findLoadingIcon().exists()).toBe(false); + }); + }); + + describe('when `isLoading` prop is `true`', () => { + beforeEach(() => { + createComponent({ ...defaultProps, isLoading: true }); + }); + + it('renders loading icon', () => { + expect(findLoadingIcon().exists()).toBe(true); + expect(findLoadingIcon().props('label')).toBe('Loading Reference'); + }); + + it('does not render clipboard button', () => { + expect(findClipboardButton().exists()).toBe(false); + }); + }); + + describe('with `clipboardTooltipText` prop', () => { + it('sets ClipboardButton `title` prop to `clipboardTooltipText` value', () => { + const mockClipboardTooltipText = 'Copy my custom value'; + createComponent({ ...defaultProps, clipboardTooltipText: mockClipboardTooltipText }); + + expect(findClipboardButton().props('title')).toBe(mockClipboardTooltipText); + }); + }); + }); +}); diff --git a/spec/frontend/sidebar/components/copy/sidebar_reference_widget_spec.js b/spec/frontend/sidebar/components/copy/sidebar_reference_widget_spec.js new file mode 100644 index 00000000000..c5161a748a9 --- /dev/null +++ b/spec/frontend/sidebar/components/copy/sidebar_reference_widget_spec.js @@ -0,0 +1,93 @@ +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import { IssuableType } from '~/issues/constants'; +import SidebarReferenceWidget from '~/sidebar/components/copy/sidebar_reference_widget.vue'; +import issueReferenceQuery from '~/sidebar/queries/issue_reference.query.graphql'; +import mergeRequestReferenceQuery from '~/sidebar/queries/merge_request_reference.query.graphql'; +import CopyableField from '~/sidebar/components/copy/copyable_field.vue'; +import { issueReferenceResponse } from '../../mock_data'; + +describe('Sidebar Reference Widget', () => { + let wrapper; + let fakeApollo; + + const mockReferenceValue = 'reference-1234'; + + const findCopyableField = () => wrapper.findComponent(CopyableField); + + const createComponent = ({ + issuableType = IssuableType.Issue, + referenceQuery = issueReferenceQuery, + referenceQueryHandler = jest.fn().mockResolvedValue(issueReferenceResponse(mockReferenceValue)), + } = {}) => { + Vue.use(VueApollo); + + fakeApollo = createMockApollo([[referenceQuery, referenceQueryHandler]]); + + wrapper = shallowMount(SidebarReferenceWidget, { + apolloProvider: fakeApollo, + provide: { + fullPath: 'group/project', + iid: '1', + }, + propsData: { + issuableType, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('when reference is loading', () => { + it('sets CopyableField `is-loading` prop to `true`', () => { + createComponent({ referenceQueryHandler: jest.fn().mockReturnValue(new Promise(() => {})) }); + expect(findCopyableField().props('isLoading')).toBe(true); + }); + }); + + describe.each([ + [IssuableType.Issue, issueReferenceQuery], + [IssuableType.MergeRequest, mergeRequestReferenceQuery], + ])('when issuableType is %s', (issuableType, referenceQuery) => { + it('sets CopyableField `value` prop to reference value', async () => { + createComponent({ + issuableType, + referenceQuery, + }); + + await waitForPromises(); + + expect(findCopyableField().props('value')).toBe(mockReferenceValue); + }); + + describe('when error occurs', () => { + it('calls createFlash with correct parameters', async () => { + const mockError = new Error('mayday'); + + createComponent({ + issuableType, + referenceQuery, + referenceQueryHandler: jest.fn().mockRejectedValue(mockError), + }); + + await waitForPromises(); + + const [ + [ + { + message, + error: { networkError }, + }, + ], + ] = wrapper.emitted('fetch-error'); + expect(message).toBe('An error occurred while fetching reference'); + expect(networkError).toEqual(mockError); + }); + }); + }); +}); |