Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/content_editor/components/bubble_menus/code_block_spec.js')
-rw-r--r--spec/frontend/content_editor/components/bubble_menus/code_block_spec.js157
1 files changed, 145 insertions, 12 deletions
diff --git a/spec/frontend/content_editor/components/bubble_menus/code_block_spec.js b/spec/frontend/content_editor/components/bubble_menus/code_block_spec.js
index 3a15ea45f40..646d068e795 100644
--- a/spec/frontend/content_editor/components/bubble_menus/code_block_spec.js
+++ b/spec/frontend/content_editor/components/bubble_menus/code_block_spec.js
@@ -1,21 +1,33 @@
import { BubbleMenu } from '@tiptap/vue-2';
-import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
-import Vue from 'vue';
+import {
+ GlDropdown,
+ GlDropdownForm,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlFormInput,
+} from '@gitlab/ui';
+import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { stubComponent } from 'helpers/stub_component';
import CodeBlockBubbleMenu from '~/content_editor/components/bubble_menus/code_block.vue';
import eventHubFactory from '~/helpers/event_hub_factory';
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
+import Diagram from '~/content_editor/extensions/diagram';
import codeBlockLanguageLoader from '~/content_editor/services/code_block_language_loader';
import { createTestEditor, emitEditorEvent } from '../../test_utils';
+const createFakeEvent = () => ({ preventDefault: jest.fn(), stopPropagation: jest.fn() });
+
describe('content_editor/components/bubble_menus/code_block', () => {
let wrapper;
let tiptapEditor;
+ let contentEditor;
let bubbleMenu;
let eventHub;
const buildEditor = () => {
- tiptapEditor = createTestEditor({ extensions: [CodeBlockHighlight] });
+ tiptapEditor = createTestEditor({ extensions: [CodeBlockHighlight, Diagram] });
+ contentEditor = { renderDiagram: jest.fn() };
eventHub = eventHubFactory();
};
@@ -23,8 +35,12 @@ describe('content_editor/components/bubble_menus/code_block', () => {
wrapper = mountExtended(CodeBlockBubbleMenu, {
provide: {
tiptapEditor,
+ contentEditor,
eventHub,
},
+ stubs: {
+ GlDropdownItem: stubComponent(GlDropdownItem),
+ },
});
};
@@ -36,7 +52,7 @@ describe('content_editor/components/bubble_menus/code_block', () => {
checked: x.props('isChecked'),
}));
- beforeEach(() => {
+ beforeEach(async () => {
buildEditor();
buildWrapper();
});
@@ -73,6 +89,15 @@ describe('content_editor/components/bubble_menus/code_block', () => {
expect(wrapper.findComponent(GlDropdown).props('text')).toBe('Javascript');
});
+ it('selects diagram sytnax for mermaid', async () => {
+ tiptapEditor.commands.insertContent('<pre lang="mermaid">test</pre>');
+ bubbleMenu = wrapper.findComponent(BubbleMenu);
+
+ await emitEditorEvent({ event: 'transaction', tiptapEditor });
+
+ expect(wrapper.findComponent(GlDropdown).props('text')).toBe('Diagram (mermaid)');
+ });
+
it("selects Custom (syntax) if the language doesn't exist in the list", async () => {
tiptapEditor.commands.insertContent('<pre lang="nomnoml">test</pre>');
bubbleMenu = wrapper.findComponent(BubbleMenu);
@@ -104,22 +129,57 @@ describe('content_editor/components/bubble_menus/code_block', () => {
});
});
+ describe('preview button', () => {
+ it('does not appear for a regular code block', async () => {
+ tiptapEditor.commands.insertContent('<pre lang="javascript">var a = 2;</pre>');
+
+ expect(wrapper.findByTestId('preview-diagram').exists()).toBe(false);
+ });
+
+ it.each`
+ diagramType | diagramCode
+ ${'mermaid'} | ${'<pre lang="mermaid">graph TD;\n A-->B;</pre>'}
+ ${'nomnoml'} | ${'<img data-diagram="nomnoml" data-diagram-src="data:text/plain;base64,WzxmcmFtZT5EZWNvcmF0b3IgcGF0dGVybl0=">'}
+ `('toggles preview for a $diagramType diagram', async ({ diagramType, diagramCode }) => {
+ tiptapEditor.commands.insertContent(diagramCode);
+
+ await nextTick();
+ await wrapper.findByTestId('preview-diagram').vm.$emit('click');
+
+ expect(tiptapEditor.getAttributes(Diagram.name)).toEqual({
+ isDiagram: true,
+ language: diagramType,
+ showPreview: false,
+ });
+
+ await wrapper.findByTestId('preview-diagram').vm.$emit('click');
+
+ expect(tiptapEditor.getAttributes(Diagram.name)).toEqual({
+ isDiagram: true,
+ language: diagramType,
+ showPreview: true,
+ });
+ });
+ });
+
describe('when opened and search is changed', () => {
beforeEach(async () => {
tiptapEditor.commands.insertContent('<pre lang="javascript">var a = 2;</pre>');
wrapper.findComponent(GlSearchBoxByType).vm.$emit('input', 'js');
- await Vue.nextTick();
+ await nextTick();
});
it('shows dropdown items', () => {
- expect(findDropdownItemsData()).toEqual([
- { text: 'Javascript', visible: true, checked: true },
- { text: 'Java', visible: true, checked: false },
- { text: 'Javascript', visible: false, checked: false },
- { text: 'JSON', visible: true, checked: false },
- ]);
+ expect(findDropdownItemsData()).toEqual(
+ expect.arrayContaining([
+ { text: 'Javascript', visible: true, checked: true },
+ { text: 'Java', visible: true, checked: false },
+ { text: 'Javascript', visible: false, checked: false },
+ { text: 'JSON', visible: true, checked: false },
+ ]),
+ );
});
describe('when dropdown item is clicked', () => {
@@ -128,7 +188,7 @@ describe('content_editor/components/bubble_menus/code_block', () => {
findDropdownItems().at(1).vm.$emit('click');
- await Vue.nextTick();
+ await nextTick();
});
it('loads language', () => {
@@ -152,5 +212,78 @@ describe('content_editor/components/bubble_menus/code_block', () => {
expect(wrapper.findComponent(GlDropdown).props('text')).toBe('Java');
});
});
+
+ describe('Create custom type', () => {
+ beforeEach(async () => {
+ tiptapEditor.commands.insertContent('<pre lang="javascript">var a = 2;</pre>');
+
+ await wrapper.findComponent(GlDropdown).vm.show();
+ await wrapper.findByTestId('create-custom-type').trigger('click');
+ });
+
+ it('shows custom language input form and hides dropdown items', () => {
+ expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(false);
+ expect(wrapper.findComponent(GlSearchBoxByType).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDropdownForm).exists()).toBe(true);
+ });
+
+ describe('on clicking back', () => {
+ it('hides the custom language input form and shows dropdown items', async () => {
+ await wrapper.findByRole('button', { name: 'Go back' }).trigger('click');
+
+ expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSearchBoxByType).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDropdownForm).exists()).toBe(false);
+ });
+ });
+
+ describe('on clicking cancel', () => {
+ it('hides the custom language input form and shows dropdown items', async () => {
+ await wrapper.findByRole('button', { name: 'Cancel' }).trigger('click');
+
+ expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSearchBoxByType).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDropdownForm).exists()).toBe(false);
+ });
+ });
+
+ describe('on dropdown hide', () => {
+ it('hides the form', async () => {
+ wrapper.findComponent(GlFormInput).setValue('foobar');
+ await wrapper.findComponent(GlDropdown).vm.$emit('hide');
+
+ expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSearchBoxByType).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDropdownForm).exists()).toBe(false);
+ });
+ });
+
+ describe('on clicking apply', () => {
+ beforeEach(async () => {
+ wrapper.findComponent(GlFormInput).setValue('foobar');
+ await wrapper.findComponent(GlDropdownForm).vm.$emit('submit', createFakeEvent());
+
+ await emitEditorEvent({ event: 'transaction', tiptapEditor });
+ });
+
+ it('hides the custom language input form and shows dropdown items', async () => {
+ expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSearchBoxByType).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDropdownForm).exists()).toBe(false);
+ });
+
+ it('updates dropdown value to the custom language type', () => {
+ expect(wrapper.findComponent(GlDropdown).props('text')).toBe('Custom (foobar)');
+ });
+
+ it('updates tiptap editor to the custom language type', () => {
+ expect(tiptapEditor.getAttributes(CodeBlockHighlight.name)).toEqual(
+ expect.objectContaining({
+ language: 'foobar',
+ }),
+ );
+ });
+ });
+ });
});
});