diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-19 10:33:21 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-19 10:33:21 +0300 |
commit | 36a59d088eca61b834191dacea009677a96c052f (patch) | |
tree | e4f33972dab5d8ef79e3944a9f403035fceea43f /spec/frontend/content_editor/components/bubble_menus/media_spec.js | |
parent | a1761f15ec2cae7c7f7bbda39a75494add0dfd6f (diff) |
Add latest changes from gitlab-org/gitlab@15-0-stable-eev15.0.0-rc42
Diffstat (limited to 'spec/frontend/content_editor/components/bubble_menus/media_spec.js')
-rw-r--r-- | spec/frontend/content_editor/components/bubble_menus/media_spec.js | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/spec/frontend/content_editor/components/bubble_menus/media_spec.js b/spec/frontend/content_editor/components/bubble_menus/media_spec.js new file mode 100644 index 00000000000..8839caea80e --- /dev/null +++ b/spec/frontend/content_editor/components/bubble_menus/media_spec.js @@ -0,0 +1,234 @@ +import { GlLink, GlForm } from '@gitlab/ui'; +import { BubbleMenu } from '@tiptap/vue-2'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import MediaBubbleMenu from '~/content_editor/components/bubble_menus/media.vue'; +import eventHubFactory from '~/helpers/event_hub_factory'; +import Image from '~/content_editor/extensions/image'; +import Audio from '~/content_editor/extensions/audio'; +import Video from '~/content_editor/extensions/video'; +import { createTestEditor, emitEditorEvent, mockChainedCommands } from '../../test_utils'; +import { + PROJECT_WIKI_ATTACHMENT_IMAGE_HTML, + PROJECT_WIKI_ATTACHMENT_AUDIO_HTML, + PROJECT_WIKI_ATTACHMENT_VIDEO_HTML, +} from '../../test_constants'; + +const TIPTAP_IMAGE_HTML = `<p> + <img src="https://gitlab.com/favicon.png" alt="gitlab favicon" title="gitlab favicon" data-canonical-src="https://gitlab.com/favicon.png"> +</p>`; + +const TIPTAP_AUDIO_HTML = `<p> + <span class="media-container audio-container"><audio src="https://gitlab.com/favicon.png" controls="true" data-setup="{}" data-title="gitlab favicon"></audio><a href="https://gitlab.com/favicon.png">gitlab favicon</a></span> +</p>`; + +const TIPTAP_VIDEO_HTML = `<p> + <span class="media-container video-container"><video src="https://gitlab.com/favicon.png" controls="true" data-setup="{}" data-title="gitlab favicon"></video><a href="https://gitlab.com/favicon.png">gitlab favicon</a></span> +</p>`; + +const createFakeEvent = () => ({ preventDefault: jest.fn(), stopPropagation: jest.fn() }); + +describe.each` + mediaType | mediaHTML | filePath | mediaOutputHTML + ${'image'} | ${PROJECT_WIKI_ATTACHMENT_IMAGE_HTML} | ${'test-file.png'} | ${TIPTAP_IMAGE_HTML} + ${'audio'} | ${PROJECT_WIKI_ATTACHMENT_AUDIO_HTML} | ${'test-file.mp3'} | ${TIPTAP_AUDIO_HTML} + ${'video'} | ${PROJECT_WIKI_ATTACHMENT_VIDEO_HTML} | ${'test-file.mp4'} | ${TIPTAP_VIDEO_HTML} +`( + 'content_editor/components/bubble_menus/media ($mediaType)', + ({ mediaType, mediaHTML, filePath, mediaOutputHTML }) => { + let wrapper; + let tiptapEditor; + let contentEditor; + let bubbleMenu; + let eventHub; + + const buildEditor = () => { + tiptapEditor = createTestEditor({ extensions: [Image, Audio, Video] }); + contentEditor = { resolveUrl: jest.fn() }; + eventHub = eventHubFactory(); + }; + + const buildWrapper = () => { + wrapper = mountExtended(MediaBubbleMenu, { + provide: { + tiptapEditor, + contentEditor, + eventHub, + }, + }); + }; + + const selectFile = async (file) => { + const input = wrapper.find({ ref: 'fileSelector' }); + + // override the property definition because `input.files` isn't directly modifyable + Object.defineProperty(input.element, 'files', { value: [file], writable: true }); + await input.trigger('change'); + }; + + const expectLinkButtonsToExist = (exist = true) => { + expect(wrapper.findComponent(GlLink).exists()).toBe(exist); + expect(wrapper.findByTestId('copy-media-src').exists()).toBe(exist); + expect(wrapper.findByTestId('edit-media').exists()).toBe(exist); + expect(wrapper.findByTestId('delete-media').exists()).toBe(exist); + }; + + beforeEach(async () => { + buildEditor(); + buildWrapper(); + + tiptapEditor + .chain() + .insertContent(mediaHTML) + .setNodeSelection(4) // select the media + .run(); + + contentEditor.resolveUrl.mockResolvedValue(`/group1/project1/-/wikis/${filePath}`); + + await emitEditorEvent({ event: 'transaction', tiptapEditor }); + + bubbleMenu = wrapper.findComponent(BubbleMenu); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders bubble menu component', async () => { + expect(bubbleMenu.props('editor')).toBe(tiptapEditor); + expect(bubbleMenu.classes()).toEqual(['gl-shadow', 'gl-rounded-base', 'gl-bg-white']); + }); + + it('shows a clickable link to the image', async () => { + const link = wrapper.findComponent(GlLink); + expect(link.attributes()).toEqual( + expect.objectContaining({ + href: `/group1/project1/-/wikis/${filePath}`, + 'aria-label': filePath, + title: filePath, + target: '_blank', + }), + ); + expect(link.text()).toBe(filePath); + }); + + describe('copy button', () => { + it(`copies the canonical link to the ${mediaType} to clipboard`, async () => { + jest.spyOn(navigator.clipboard, 'writeText'); + + await wrapper.findByTestId('copy-media-src').vm.$emit('click'); + + expect(navigator.clipboard.writeText).toHaveBeenCalledWith(filePath); + }); + }); + + describe(`remove ${mediaType} button`, () => { + it(`removes the ${mediaType}`, async () => { + await wrapper.findByTestId('delete-media').vm.$emit('click'); + + expect(tiptapEditor.getHTML()).toBe('<p>\n \n</p>'); + }); + }); + + describe(`replace ${mediaType} button`, () => { + it('uploads and replaces the selected image when file input changes', async () => { + const commands = mockChainedCommands(tiptapEditor, [ + 'focus', + 'deleteSelection', + 'uploadAttachment', + 'run', + ]); + const file = new File(['foo'], 'foo.png', { type: 'image/png' }); + + await wrapper.findByTestId('replace-media').vm.$emit('click'); + await selectFile(file); + + expect(commands.focus).toHaveBeenCalled(); + expect(commands.deleteSelection).toHaveBeenCalled(); + expect(commands.uploadAttachment).toHaveBeenCalledWith({ file }); + expect(commands.run).toHaveBeenCalled(); + }); + }); + + describe('edit button', () => { + let mediaSrcInput; + let mediaTitleInput; + let mediaAltInput; + + beforeEach(async () => { + await wrapper.findByTestId('edit-media').vm.$emit('click'); + + mediaSrcInput = wrapper.findByTestId('media-src'); + mediaTitleInput = wrapper.findByTestId('media-title'); + mediaAltInput = wrapper.findByTestId('media-alt'); + }); + + it('hides the link and copy/edit/remove link buttons', async () => { + expectLinkButtonsToExist(false); + }); + + it(`shows a form to edit the ${mediaType} src/title/alt`, () => { + expect(wrapper.findComponent(GlForm).exists()).toBe(true); + + expect(mediaSrcInput.element.value).toBe(filePath); + expect(mediaTitleInput.element.value).toBe(''); + expect(mediaAltInput.element.value).toBe('test-file'); + }); + + describe('after making changes in the form and clicking apply', () => { + beforeEach(async () => { + mediaSrcInput.setValue('https://gitlab.com/favicon.png'); + mediaAltInput.setValue('gitlab favicon'); + mediaTitleInput.setValue('gitlab favicon'); + + contentEditor.resolveUrl.mockResolvedValue('https://gitlab.com/favicon.png'); + + await wrapper.findComponent(GlForm).vm.$emit('submit', createFakeEvent()); + }); + + it(`updates prosemirror doc with new src to the ${mediaType}`, async () => { + expect(tiptapEditor.getHTML()).toBe(mediaOutputHTML); + }); + + it(`updates the link to the ${mediaType} in the bubble menu`, () => { + const link = wrapper.findComponent(GlLink); + expect(link.attributes()).toEqual( + expect.objectContaining({ + href: 'https://gitlab.com/favicon.png', + 'aria-label': 'https://gitlab.com/favicon.png', + title: 'https://gitlab.com/favicon.png', + target: '_blank', + }), + ); + expect(link.text()).toBe('https://gitlab.com/favicon.png'); + }); + }); + + describe('after making changes in the form and clicking cancel', () => { + beforeEach(async () => { + mediaSrcInput.setValue('https://gitlab.com/favicon.png'); + mediaAltInput.setValue('gitlab favicon'); + mediaTitleInput.setValue('gitlab favicon'); + + await wrapper.findByTestId('cancel-editing-media').vm.$emit('click'); + }); + + it('hides the form and shows the copy/edit/remove link buttons', () => { + expectLinkButtonsToExist(); + }); + + it(`resets the form with old values of the ${mediaType} from prosemirror`, async () => { + // click edit once again to show the form back + await wrapper.findByTestId('edit-media').vm.$emit('click'); + + mediaSrcInput = wrapper.findByTestId('media-src'); + mediaTitleInput = wrapper.findByTestId('media-title'); + mediaAltInput = wrapper.findByTestId('media-alt'); + + expect(mediaSrcInput.element.value).toBe(filePath); + expect(mediaAltInput.element.value).toBe('test-file'); + expect(mediaTitleInput.element.value).toBe(''); + }); + }); + }); + }, +); |