From 6ed4ec3e0b1340f96b7c043ef51d1b33bbe85fde Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 19 Sep 2022 23:18:09 +0000 Subject: Add latest changes from gitlab-org/gitlab@15-4-stable-ee --- .../content_editor_integration_spec.js | 111 ++++++++++++++------- spec/frontend_integration/ide/helpers/start.js | 4 +- 2 files changed, 79 insertions(+), 36 deletions(-) (limited to 'spec/frontend_integration') diff --git a/spec/frontend_integration/content_editor/content_editor_integration_spec.js b/spec/frontend_integration/content_editor/content_editor_integration_spec.js index 12cd6dcad83..c0c6b5e5dc8 100644 --- a/spec/frontend_integration/content_editor/content_editor_integration_spec.js +++ b/spec/frontend_integration/content_editor/content_editor_integration_spec.js @@ -1,6 +1,7 @@ import { nextTick } from 'vue'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import { ContentEditor } from '~/content_editor'; +import waitForPromises from 'helpers/wait_for_promises'; /** * This spec exercises some workflows in the Content Editor without mocking @@ -10,32 +11,38 @@ import { ContentEditor } from '~/content_editor'; describe('content_editor', () => { let wrapper; let renderMarkdown; - let contentEditorService; - const buildWrapper = () => { - renderMarkdown = jest.fn(); + const buildWrapper = ({ markdown = '' } = {}) => { wrapper = mountExtended(ContentEditor, { propsData: { renderMarkdown, uploadsPath: '/', - }, - listeners: { - initialized(contentEditor) { - contentEditorService = contentEditor; - }, + markdown, }, }); }; + const waitUntilContentIsLoaded = async () => { + await waitForPromises(); + await nextTick(); + }; + + const mockRenderMarkdownResponse = (response) => { + renderMarkdown.mockImplementation((markdown) => (markdown ? response : null)); + }; + + beforeEach(() => { + renderMarkdown = jest.fn(); + }); + describe('when loading initial content', () => { describe('when the initial content is empty', () => { it('still hides the loading indicator', async () => { - buildWrapper(); + mockRenderMarkdownResponse(''); - renderMarkdown.mockResolvedValue(''); + buildWrapper(); - await contentEditorService.setSerializedContent(''); - await nextTick(); + await waitUntilContentIsLoaded(); expect(wrapper.findByTestId('content-editor-loading-indicator').exists()).toBe(false); }); @@ -44,14 +51,15 @@ describe('content_editor', () => { describe('when the initial content is not empty', () => { const initialContent = '

bold text

'; beforeEach(async () => { - buildWrapper(); + mockRenderMarkdownResponse(initialContent); - renderMarkdown.mockResolvedValue(initialContent); + buildWrapper({ + markdown: '**bold text**', + }); - await contentEditorService.setSerializedContent('**bold text**'); - await nextTick(); + await waitUntilContentIsLoaded(); }); - it('hides the loading indicator', async () => { + it('hides the loading indicator', () => { expect(wrapper.findByTestId('content-editor-loading-indicator').exists()).toBe(false); }); @@ -70,27 +78,29 @@ describe('content_editor', () => { }); it('processes and renders footnote ids alongside the footnote definition', async () => { - buildWrapper(); - - await contentEditorService.setSerializedContent(` + buildWrapper({ + markdown: ` This reference tag is a mix of letters and numbers [^footnote]. [^footnote]: This is another footnote. - `); - await nextTick(); + `, + }); + + await waitUntilContentIsLoaded(); expect(wrapper.text()).toContain('footnote: This is another footnote'); }); it('processes and displays reference definitions', async () => { - buildWrapper(); - - await contentEditorService.setSerializedContent(` + buildWrapper({ + markdown: ` [GitLab][gitlab] [gitlab]: https://gitlab.com - `); - await nextTick(); + `, + }); + + await waitUntilContentIsLoaded(); expect(wrapper.find('pre').text()).toContain('[gitlab]: https://gitlab.com'); }); @@ -99,9 +109,7 @@ This reference tag is a mix of letters and numbers [^footnote]. it('renders table of contents', async () => { jest.useFakeTimers(); - buildWrapper(); - - renderMarkdown.mockResolvedValue(` + renderMarkdown.mockResolvedValueOnce(`

@@ -112,18 +120,53 @@ This reference tag is a mix of letters and numbers [^footnote].

`); - await contentEditorService.setSerializedContent(` + buildWrapper({ + markdown: ` [TOC] # Heading 1 ## Heading 2 - `); + `, + }); - await nextTick(); - jest.runAllTimers(); + await waitUntilContentIsLoaded(); expect(wrapper.findByTestId('table-of-contents').text()).toContain('Heading 1'); expect(wrapper.findByTestId('table-of-contents').text()).toContain('Heading 2'); }); + + describe('when pasting content', () => { + const buildClipboardData = (data = {}) => ({ + clipboardData: { + getData(mimeType) { + return data[mimeType]; + }, + types: Object.keys(data), + }, + }); + + describe('when the clipboard does not contain text/html data', () => { + it('processes the clipboard content as markdown', async () => { + const processedMarkdown = 'bold text'; + + buildWrapper(); + + await waitUntilContentIsLoaded(); + + mockRenderMarkdownResponse(processedMarkdown); + + wrapper.find('[contenteditable]').trigger( + 'paste', + buildClipboardData({ + 'text/plain': '**bold text**', + }), + ); + + await waitUntilContentIsLoaded(); + + expect(wrapper.find('[contenteditable]').html()).toContain(processedMarkdown); + }); + }); + }); }); diff --git a/spec/frontend_integration/ide/helpers/start.js b/spec/frontend_integration/ide/helpers/start.js index 925db12f36e..40e6a725358 100644 --- a/spec/frontend_integration/ide/helpers/start.js +++ b/spec/frontend_integration/ide/helpers/start.js @@ -1,7 +1,7 @@ import { editor as monacoEditor } from 'monaco-editor'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'helpers/test_constants'; -import { initIde } from '~/ide'; +import { initLegacyWebIDE } from '~/ide'; import extendStore from '~/ide/stores/extend'; import { getProject, getEmptyProject } from 'jest/../frontend_integration/test_helpers/fixtures'; import { IDE_DATASET } from './mock_data'; @@ -16,7 +16,7 @@ export default (container, { isRepoEmpty = false, path = '', mrId = '' } = {}) = const el = document.createElement('div'); Object.assign(el.dataset, IDE_DATASET, { project: JSON.stringify(project) }); container.appendChild(el); - const vm = initIde(el, { extendStore }); + const vm = initLegacyWebIDE(el, { extendStore }); // We need to dispose of editor Singleton things or tests will bump into eachother vm.$on('destroy', () => monacoEditor.getModels().forEach((model) => model.dispose())); -- cgit v1.2.1