Commit 94b0ee9d authored by Enrique Alcantara's avatar Enrique Alcantara

Test the selection of a text style

parent 931bd0b6
...@@ -2,16 +2,22 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; ...@@ -2,16 +2,22 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ToolbarTextStyleDropdown from '~/content_editor/components/toolbar_text_style_dropdown.vue'; import ToolbarTextStyleDropdown from '~/content_editor/components/toolbar_text_style_dropdown.vue';
import { TEXT_STYLE_DROPDOWN_ITEMS } from '~/content_editor/constants'; import { TEXT_STYLE_DROPDOWN_ITEMS } from '~/content_editor/constants';
import { createContentEditor } from '~/content_editor/services/create_content_editor'; import { createTestContentEditorExtension, createTestEditor } from '../test_utils';
describe('content_editor/components/toolbar_headings_dropdown', () => { describe('content_editor/components/toolbar_headings_dropdown', () => {
let wrapper; let wrapper;
let tiptapEditor; let tiptapEditor;
let commandMocks;
const buildEditor = () => { const buildEditor = () => {
tiptapEditor = createContentEditor({ const testExtension = createTestContentEditorExtension({
renderMarkdown: () => true, commands: TEXT_STYLE_DROPDOWN_ITEMS.map((item) => item.editorCommand),
}).tiptapEditor; });
commandMocks = testExtension.commandMocks;
tiptapEditor = createTestEditor({
extensions: [testExtension.tiptapExtension],
});
jest.spyOn(tiptapEditor, 'isActive'); jest.spyOn(tiptapEditor, 'isActive');
}; };
...@@ -41,8 +47,8 @@ describe('content_editor/components/toolbar_headings_dropdown', () => { ...@@ -41,8 +47,8 @@ describe('content_editor/components/toolbar_headings_dropdown', () => {
it('renders all text styles as dropdown items', () => { it('renders all text styles as dropdown items', () => {
buildWrapper(); buildWrapper();
TEXT_STYLE_DROPDOWN_ITEMS.forEach((heading) => { TEXT_STYLE_DROPDOWN_ITEMS.forEach((textStyle) => {
expect(wrapper.findByText(heading.label).exists()).toBe(true); expect(wrapper.findByText(textStyle.label).exists()).toBe(true);
}); });
}); });
...@@ -91,4 +97,35 @@ describe('content_editor/components/toolbar_headings_dropdown', () => { ...@@ -91,4 +97,35 @@ describe('content_editor/components/toolbar_headings_dropdown', () => {
expect(findDropdown().props().text).toBe('Text style'); expect(findDropdown().props().text).toBe('Text style');
}); });
}); });
describe('when a text style is selected', () => {
it('executes the tiptap command related to that text style', () => {
buildWrapper();
TEXT_STYLE_DROPDOWN_ITEMS.forEach((textStyle, index) => {
const { editorCommand, commandParams } = textStyle;
wrapper.findAllComponents(GlDropdownItem).at(index).vm.$emit('click');
expect(commandMocks[editorCommand]).toHaveBeenCalledWith(commandParams || {});
});
});
it('emits execute event with contentType and value params that indicates the heading level', () => {
TEXT_STYLE_DROPDOWN_ITEMS.forEach((textStyle, index) => {
buildWrapper();
const { contentType, commandParams } = textStyle;
wrapper.findAllComponents(GlDropdownItem).at(index).vm.$emit('click');
expect(wrapper.emitted('execute')).toEqual([
[
{
contentType,
value: commandParams?.level,
},
],
]);
wrapper.destroy();
});
});
});
}); });
import { Node } from '@tiptap/core'; import { Node } from '@tiptap/core';
import { Document } from '@tiptap/extension-document';
import { Paragraph } from '@tiptap/extension-paragraph';
import { Text } from '@tiptap/extension-text';
import { Editor } from '@tiptap/vue-2';
export const createTestContentEditorExtension = () => ({ /**
tiptapExtension: Node.create({ * Creates an instance of the Tiptap Editor class
name: 'label', * with a minimal configuration for testing purposes.
priority: 101, *
inline: true, * It only includes the Document, Text, and Paragraph
group: 'inline', * extensions.
addAttributes() { *
return { * @param {Array} config.extensions One or more extensions to
labelName: { * include in the editor
default: null, * @returns An instance of a Tiptap’s Editor class
parseHTML: (element) => { */
return { labelName: element.dataset.labelName }; export const createTestEditor = ({ extensions = [] }) => {
return new Editor({
extensions: [Document, Text, Paragraph, ...extensions],
});
};
/**
* Creates a Content Editor extension for testing
* purposes.
*
* @param {Array} config.commands A list of command names
* to include in the test extension. This utility will create
* Jest mock functions for each command name.
* @returns An object with the following properties:
*
* tiptapExtension A Node tiptap extension
* commandMocks Jest mock functions for each created command
* serializer A markdown serializer for the extension
*/
export const createTestContentEditorExtension = ({ commands = [] } = {}) => {
const commandMocks = commands.reduce(
(accum, commandName) => ({
...accum,
[commandName]: jest.fn(),
}),
{},
);
return {
commandMocks,
tiptapExtension: Node.create({
name: 'label',
priority: 101,
inline: true,
group: 'inline',
addCommands() {
return commands.reduce(
(accum, commandName) => ({
...accum,
[commandName]: (...params) => () => commandMocks[commandName](...params),
}),
{},
);
},
addAttributes() {
return {
labelName: {
default: null,
parseHTML: (element) => {
return { labelName: element.dataset.labelName };
},
}, },
}, };
}; },
}, parseHTML() {
parseHTML() { return [
return [ {
{ tag: 'span[data-reference="label"]',
tag: 'span[data-reference="label"]', },
}, ];
]; },
}, renderHTML({ HTMLAttributes }) {
renderHTML({ HTMLAttributes }) { return ['span', HTMLAttributes, 0];
return ['span', HTMLAttributes, 0]; },
}),
serializer: (state, node) => {
state.write(`~${node.attrs.labelName}`);
state.closeBlock(node);
}, },
}), };
serializer: (state, node) => { };
state.write(`~${node.attrs.labelName}`);
state.closeBlock(node);
},
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment