Commit 554c0711 authored by Enrique Alcantara's avatar Enrique Alcantara

ContentEditor toolbar button

A toolbar button provides a view for the status of a
content type in the editor. It also allows executing
a command when the button is clicked
parent 7172e12e
<script>
import { GlButton, GlIcon, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
export default {
components: {
GlButton,
GlIcon,
},
directives: {
GlTooltip,
},
props: {
iconName: {
type: String,
required: true,
},
editor: {
type: Object,
required: true,
},
contentType: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
executeCommand: {
type: Boolean,
required: false,
default: true,
},
},
computed: {
isActive() {
return this.editor.isActive[this.contentType]() && this.editor.focused;
},
},
methods: {
execute() {
const { contentType } = this;
if (this.executeCommand) {
this.editor.commands[contentType]();
}
this.$emit('click', { contentType });
},
},
};
</script>
<template>
<gl-button
v-gl-tooltip
category="tertiary"
size="small"
:class="{ active: isActive }"
:aria-label="label"
:title="label"
@click="execute"
>
<gl-icon :name="iconName" :size="16" />
</gl-button>
</template>
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`content_editor/components/toolbar_button displays tertiary, small button with a provided label and icon 1`] = `
"<b-button-stub event=\\"click\\" routertag=\\"a\\" size=\\"sm\\" variant=\\"default\\" type=\\"button\\" tag=\\"button\\" aria-label=\\"Bold\\" title=\\"Bold\\" class=\\"gl-button btn-default-tertiary\\">
<!---->
<!----> <span class=\\"gl-button-text\\"><gl-icon-stub name=\\"bold\\" size=\\"16\\"></gl-icon-stub></span></b-button-stub>"
`;
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import ToolbarButton from '~/content_editor/components/toolbar_button.vue';
describe('content_editor/components/toolbar_button', () => {
let wrapper;
let editor;
const CONTENT_TYPE = 'bold';
const ICON_NAME = 'bold';
const LABEL = 'Bold';
const buildEditor = () => {
editor = {
isActive: {
[CONTENT_TYPE]: jest.fn(),
},
commands: {
[CONTENT_TYPE]: jest.fn(),
},
};
};
const buildWrapper = (propsData = {}) => {
wrapper = shallowMount(ToolbarButton, {
stubs: {
GlButton,
},
propsData: {
editor,
contentType: CONTENT_TYPE,
iconName: ICON_NAME,
label: LABEL,
...propsData,
},
});
};
const findButton = () => wrapper.findComponent(GlButton);
beforeEach(() => {
buildEditor();
});
afterEach(() => {
wrapper.destroy();
});
it('displays tertiary, small button with a provided label and icon', () => {
buildWrapper();
expect(findButton().html()).toMatchSnapshot();
});
it.each`
editorState | outcomeDescription | outcome
${{ isActive: true, focused: true }} | ${'button is active'} | ${true}
${{ isActive: false, focused: true }} | ${'button is not active'} | ${false}
${{ isActive: true, focused: false }} | ${'button is not active '} | ${false}
`('$outcomeDescription when when editor state is $editorState', ({ editorState, outcome }) => {
editor.isActive[CONTENT_TYPE].mockReturnValueOnce(editorState.isActive);
editor.focused = editorState.focused;
buildWrapper();
expect(findButton().classes().includes('active')).toBe(outcome);
});
describe('when button is clicked', () => {
it('executes the content type command when executeCommand = true', async () => {
buildWrapper({ executeCommand: true });
await findButton().trigger('click');
expect(editor.commands[CONTENT_TYPE]).toHaveBeenCalled();
expect(wrapper.emitted().click).toHaveLength(1);
});
it('does not executes the content type command when executeCommand = false', async () => {
buildWrapper({ executeCommand: false });
await findButton().trigger('click');
expect(editor.commands[CONTENT_TYPE]).not.toHaveBeenCalled();
expect(wrapper.emitted().click).toHaveLength(1);
});
});
});
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