@zipify/wysiwyg 1.0.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +18 -0
- package/.eslintrc.js +253 -0
- package/.github/actions/deploy-example/action.yaml +61 -0
- package/.github/actions/lint-css/action.yaml +15 -0
- package/.github/actions/lint-js/action.yaml +22 -0
- package/.github/actions/setup/action.yaml +19 -0
- package/.github/actions/unit-tests/action.yaml +13 -0
- package/.github/actions/unit-tests/jest.config.js +8 -0
- package/.github/dependabot.yaml +17 -0
- package/.github/pull_request_template.md +17 -0
- package/.github/workflows/frontend-ci.yaml +120 -0
- package/.husky/pre-commit +4 -0
- package/.lintstagedrc +12 -0
- package/.release-it.json +6 -0
- package/.stylelintrc +110 -0
- package/README.md +61 -0
- package/babel.config.js +15 -0
- package/ci/example/deploy.sh +25 -0
- package/config/jest/TestEnvironment.js +27 -0
- package/config/jest/matchers/index.js +6 -0
- package/config/jest/matchers/toElementHasStyle.js +27 -0
- package/config/jest/matchers/toVueContainComponent.js +20 -0
- package/config/jest/matchers/toVueContainElement.js +34 -0
- package/config/jest/matchers/toVueContainLazyComponent.js +19 -0
- package/config/jest/matchers/toVueEmpty.js +16 -0
- package/config/jest/matchers/toVuexActionHasBeenDispatched.js +19 -0
- package/config/jest/setupMatchers.js +4 -0
- package/config/jest/setupTests.js +32 -0
- package/config/jest/typing.d.ts +14 -0
- package/config/svgo.js +22 -0
- package/config/webpack/example.config.js +86 -0
- package/config/webpack/loaders/index.js +6 -0
- package/config/webpack/loaders/js-loader.js +5 -0
- package/config/webpack/loaders/style-loader.js +7 -0
- package/config/webpack/loaders/svg-loader.js +4 -0
- package/config/webpack/loaders/vue-loader.js +4 -0
- package/config/webpack/settings.js +9 -0
- package/example/ExampleApp.vue +136 -0
- package/example/example.html +17 -0
- package/example/example.js +19 -0
- package/example/fonts.js +474 -0
- package/example/presets.js +245 -0
- package/example/tooltip/Tooltip.js +241 -0
- package/example/tooltip/TooltipManager.js +132 -0
- package/example/tooltip/index.js +3 -0
- package/example/tooltip/modifiers/TooltipCloseOnScrollModifier.js +73 -0
- package/example/tooltip/modifiers/index.js +1 -0
- package/example/tooltip/tooltip.css +95 -0
- package/jest.config.js +17 -0
- package/lib/Wysiwyg.vue +156 -0
- package/lib/__mocks__/svgMock.js +1 -0
- package/lib/__tests__/utils/NodeFactory.js +67 -0
- package/lib/__tests__/utils/index.js +4 -0
- package/lib/__tests__/utils/setReadonlyProperty.js +9 -0
- package/lib/__tests__/utils/waitAsyncOperation.js +6 -0
- package/lib/__tests__/utils/withComponentContext.js +14 -0
- package/lib/assets/icons.svg +69 -0
- package/lib/components/base/Button.vue +117 -0
- package/lib/components/base/ButtonToggle.vue +40 -0
- package/lib/components/base/FieldLabel.vue +28 -0
- package/lib/components/base/Icon.vue +67 -0
- package/lib/components/base/Modal.vue +116 -0
- package/lib/components/base/NumberField.vue +242 -0
- package/lib/components/base/Range.vue +196 -0
- package/lib/components/base/ScrollView.vue +60 -0
- package/lib/components/base/__tests__/Button.test.js +50 -0
- package/lib/components/base/__tests__/Icon.test.js +56 -0
- package/lib/components/base/__tests__/Modal.test.js +69 -0
- package/lib/components/base/__tests__/Range.test.js +39 -0
- package/lib/components/base/colorPicker/ColorPicker.vue +93 -0
- package/lib/components/base/colorPicker/composables/__tests__/usePickerApi.test.js +81 -0
- package/lib/components/base/colorPicker/composables/index.js +2 -0
- package/lib/components/base/colorPicker/composables/usePickerApi.js +35 -0
- package/lib/components/base/colorPicker/composables/usePickerHotkeys.js +25 -0
- package/lib/components/base/colorPicker/index.js +1 -0
- package/lib/components/base/composables/__tests__/useActivatedListener.test.js +89 -0
- package/lib/components/base/composables/__tests__/useDeselectionLock.test.js +80 -0
- package/lib/components/base/composables/__tests__/useElementRef.test.js +29 -0
- package/lib/components/base/composables/__tests__/useModalToggler.test.js +55 -0
- package/lib/components/base/composables/__tests__/useNumberValue.test.js +153 -0
- package/lib/components/base/composables/__tests__/useScrollView.test.js +43 -0
- package/lib/components/base/composables/__tests__/useTempValue.test.js +38 -0
- package/lib/components/base/composables/index.js +7 -0
- package/lib/components/base/composables/useActivatedListener.js +23 -0
- package/lib/components/base/composables/useDeselectionLock.js +35 -0
- package/lib/components/base/composables/useElementRef.js +5 -0
- package/lib/components/base/composables/useModalToggler.js +58 -0
- package/lib/components/base/composables/useNumberValue.js +53 -0
- package/lib/components/base/composables/useScrollView.js +22 -0
- package/lib/components/base/composables/useTempValue.js +11 -0
- package/lib/components/base/dropdown/Dropdown.vue +88 -0
- package/lib/components/base/dropdown/DropdownActivator.vue +81 -0
- package/lib/components/base/dropdown/DropdownDivider.vue +21 -0
- package/lib/components/base/dropdown/DropdownGroup.vue +55 -0
- package/lib/components/base/dropdown/DropdownMenu.vue +62 -0
- package/lib/components/base/dropdown/DropdownOption.vue +91 -0
- package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +54 -0
- package/lib/components/base/dropdown/__tests__/DropdownMenu.test.js +67 -0
- package/lib/components/base/dropdown/__tests__/DropdownOption.test.js +81 -0
- package/lib/components/base/dropdown/composables/__tests__/useActiveOptionManager.test.js +41 -0
- package/lib/components/base/dropdown/composables/__tests__/useDropdownEntityTitle.test.js +24 -0
- package/lib/components/base/dropdown/composables/index.js +2 -0
- package/lib/components/base/dropdown/composables/useActiveOptionManager.js +25 -0
- package/lib/components/base/dropdown/composables/useDropdownEntityTitle.js +5 -0
- package/lib/components/base/dropdown/index.js +2 -0
- package/lib/components/base/dropdown/injectionTokens.js +5 -0
- package/lib/components/base/index.js +11 -0
- package/lib/components/index.js +1 -0
- package/lib/components/toolbar/Toolbar.vue +56 -0
- package/lib/components/toolbar/ToolbarDevice.vue +35 -0
- package/lib/components/toolbar/ToolbarDivider.vue +50 -0
- package/lib/components/toolbar/ToolbarFull.vue +94 -0
- package/lib/components/toolbar/ToolbarGroup.vue +18 -0
- package/lib/components/toolbar/ToolbarRow.vue +19 -0
- package/lib/components/toolbar/__tests__/Toolbar.test.js +33 -0
- package/lib/components/toolbar/__tests__/ToolbarDivider.test.js +26 -0
- package/lib/components/toolbar/controls/AlignmentControl.vue +72 -0
- package/lib/components/toolbar/controls/AlignmentDeviceControl.vue +67 -0
- package/lib/components/toolbar/controls/BackgroundColorControl.vue +48 -0
- package/lib/components/toolbar/controls/CaseStyleControl.vue +54 -0
- package/lib/components/toolbar/controls/FontColorControl.vue +48 -0
- package/lib/components/toolbar/controls/FontFamilyControl.vue +96 -0
- package/lib/components/toolbar/controls/FontSizeControl.vue +45 -0
- package/lib/components/toolbar/controls/FontWeightControl.vue +43 -0
- package/lib/components/toolbar/controls/ItalicControl.vue +47 -0
- package/lib/components/toolbar/controls/LineHeightControl.vue +102 -0
- package/lib/components/toolbar/controls/ListControl.vue +86 -0
- package/lib/components/toolbar/controls/RemoveFormatControl.vue +37 -0
- package/lib/components/toolbar/controls/StrikeThroughControl.vue +44 -0
- package/lib/components/toolbar/controls/StylePresetControl.vue +95 -0
- package/lib/components/toolbar/controls/SuperscriptControl.vue +44 -0
- package/lib/components/toolbar/controls/UnderlineControl.vue +44 -0
- package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +51 -0
- package/lib/components/toolbar/controls/__tests__/AlignmentDeviceControl.test.js +77 -0
- package/lib/components/toolbar/controls/__tests__/BackgroundColorControl.test.js +59 -0
- package/lib/components/toolbar/controls/__tests__/CaseStyleControl.test.js +43 -0
- package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +59 -0
- package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +57 -0
- package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +47 -0
- package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +45 -0
- package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +63 -0
- package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +120 -0
- package/lib/components/toolbar/controls/__tests__/ListControl.test.js +82 -0
- package/lib/components/toolbar/controls/__tests__/RemoveFormatControl.test.js +34 -0
- package/lib/components/toolbar/controls/__tests__/StrikeThroughControl.test.js +44 -0
- package/lib/components/toolbar/controls/__tests__/StylePresetControl.test.js +129 -0
- package/lib/components/toolbar/controls/__tests__/SuperscriptControl.test.js +44 -0
- package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +44 -0
- package/lib/components/toolbar/controls/composables/__tests__/useRecentFonts.test.js +69 -0
- package/lib/components/toolbar/controls/composables/index.js +1 -0
- package/lib/components/toolbar/controls/composables/useRecentFonts.js +18 -0
- package/lib/components/toolbar/controls/index.js +16 -0
- package/lib/components/toolbar/index.js +1 -0
- package/lib/composables/__tests__/__snapshots__/useEditor.test.js.snap +24 -0
- package/lib/composables/__tests__/useEditor.test.js +67 -0
- package/lib/composables/__tests__/useToolbar.test.js +56 -0
- package/lib/composables/index.js +2 -0
- package/lib/composables/useEditor.js +21 -0
- package/lib/composables/useToolbar.js +44 -0
- package/lib/directives/__tests__/outClick.test.js +86 -0
- package/lib/directives/__tests__/tooltip.test.js +39 -0
- package/lib/directives/index.js +2 -0
- package/lib/directives/outClick.js +37 -0
- package/lib/directives/tooltip.js +7 -0
- package/lib/enums/Alignments.js +6 -0
- package/lib/enums/CaseStyles.js +5 -0
- package/lib/enums/Devices.js +15 -0
- package/lib/enums/ListTypes.js +23 -0
- package/lib/enums/NodeTypes.js +12 -0
- package/lib/enums/TextSettings.js +30 -0
- package/lib/enums/index.js +6 -0
- package/lib/extensions/Alignment.js +67 -0
- package/lib/extensions/BackgroundColor.js +28 -0
- package/lib/extensions/CaseStyle.js +36 -0
- package/lib/extensions/DeviceManager.js +16 -0
- package/lib/extensions/FontColor.js +36 -0
- package/lib/extensions/FontFamily.js +62 -0
- package/lib/extensions/FontSize.js +74 -0
- package/lib/extensions/FontStyle.js +62 -0
- package/lib/extensions/FontWeight.js +56 -0
- package/lib/extensions/LineHeight.js +60 -0
- package/lib/extensions/StylePreset.js +168 -0
- package/lib/extensions/Superscript.js +5 -0
- package/lib/extensions/TextDecoration.js +97 -0
- package/lib/extensions/__tests__/Alignment.test.js +107 -0
- package/lib/extensions/__tests__/BackgroundColor.test.js +75 -0
- package/lib/extensions/__tests__/CaseStyle.test.js +58 -0
- package/lib/extensions/__tests__/FontColor.test.js +85 -0
- package/lib/extensions/__tests__/FontFamily.test.js +171 -0
- package/lib/extensions/__tests__/FontSize.test.js +183 -0
- package/lib/extensions/__tests__/FontStyle.test.js +136 -0
- package/lib/extensions/__tests__/FontWeight.test.js +151 -0
- package/lib/extensions/__tests__/LineHeight.test.js +106 -0
- package/lib/extensions/__tests__/StylePreset.test.js +400 -0
- package/lib/extensions/__tests__/TextDecoration.test.js +258 -0
- package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +29 -0
- package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +28 -0
- package/lib/extensions/__tests__/__snapshots__/CaseStyle.test.js.snap +69 -0
- package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +28 -0
- package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +158 -0
- package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +140 -0
- package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +87 -0
- package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +140 -0
- package/lib/extensions/__tests__/__snapshots__/LineHeight.test.js.snap +29 -0
- package/lib/extensions/__tests__/__snapshots__/StylePreset.test.js.snap +310 -0
- package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +206 -0
- package/lib/extensions/core/NodeProcessor.js +32 -0
- package/lib/extensions/core/SelectionProcessor.js +37 -0
- package/lib/extensions/core/TextProcessor.js +57 -0
- package/lib/extensions/core/__tests__/NodeProcessor.test.js +120 -0
- package/lib/extensions/core/__tests__/SelectionProcessor.test.js +78 -0
- package/lib/extensions/core/__tests__/TextProcessor.test.js +61 -0
- package/lib/extensions/core/__tests__/__snapshots__/NodeProcessor.test.js.snap +93 -0
- package/lib/extensions/core/__tests__/__snapshots__/TextProcessor.test.js.snap +43 -0
- package/lib/extensions/core/index.js +17 -0
- package/lib/extensions/core/inputRules/closeDoubleQuote.js +6 -0
- package/lib/extensions/core/inputRules/closeSingleQuote.js +6 -0
- package/lib/extensions/core/inputRules/copyright.js +6 -0
- package/lib/extensions/core/inputRules/ellipsis.js +6 -0
- package/lib/extensions/core/inputRules/emDash.js +6 -0
- package/lib/extensions/core/inputRules/index.js +9 -0
- package/lib/extensions/core/inputRules/openDoubleQuote.js +6 -0
- package/lib/extensions/core/inputRules/openSingleQuote.js +6 -0
- package/lib/extensions/core/inputRules/registeredTrademark.js +6 -0
- package/lib/extensions/core/inputRules/trademark.js +6 -0
- package/lib/extensions/index.js +49 -0
- package/lib/extensions/list/List.js +81 -0
- package/lib/extensions/list/ListItem.js +12 -0
- package/lib/extensions/list/__tests__/List.test.js +130 -0
- package/lib/extensions/list/__tests__/__snapshots__/List.test.js.snap +212 -0
- package/lib/extensions/list/index.js +1 -0
- package/lib/index.js +1 -0
- package/lib/injectionTokens.js +7 -0
- package/lib/models/Font.js +37 -0
- package/lib/models/__tests__/Font.test.js +58 -0
- package/lib/models/index.js +1 -0
- package/lib/services/FavoriteColors.js +6 -0
- package/lib/services/JsonSerializer.js +15 -0
- package/lib/services/Storage.js +49 -0
- package/lib/services/index.js +3 -0
- package/lib/styles/content.css +39 -0
- package/lib/styles/helpers/common.css +3 -0
- package/lib/styles/helpers/offsets.css +3 -0
- package/lib/styles/helpers/text.css +6 -0
- package/lib/styles/main.css +5 -0
- package/lib/styles/variables.css +57 -0
- package/lib/utils/__tests__/__snapshots__/renderInlineSetting.test.js.snap +40 -0
- package/lib/utils/__tests__/capitalize.test.js +11 -0
- package/lib/utils/__tests__/renderInlineSetting.test.js +39 -0
- package/lib/utils/capitalize.js +3 -0
- package/lib/utils/createCommand.js +3 -0
- package/lib/utils/createKeyboardShortcut.js +6 -0
- package/lib/utils/index.js +4 -0
- package/lib/utils/renderInlineSetting.js +17 -0
- package/package.json +75 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import { ref } from '@vue/composition-api';
|
|
3
|
+
import { InjectionTokens } from '../../../../injectionTokens';
|
|
4
|
+
import { Button, Dropdown } from '../../../base';
|
|
5
|
+
import StylePresetControl from '../StylePresetControl';
|
|
6
|
+
|
|
7
|
+
const createEditor = ({ presets, preset, customization } = {}) => ({
|
|
8
|
+
commands: {
|
|
9
|
+
focus: jest.fn().mockReturnThis(),
|
|
10
|
+
getPresetList: () => ref(presets || []),
|
|
11
|
+
getPreset: () => ref(preset || { id: 'regular' }),
|
|
12
|
+
getPresetCustomization: () => ref(customization || { attributes: [], marks: [] }),
|
|
13
|
+
applyPreset: jest.fn().mockReturnThis(),
|
|
14
|
+
removePresetCustomization: jest.fn().mockReturnThis(),
|
|
15
|
+
run: jest.fn()
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
chain() {
|
|
19
|
+
return this.commands;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
function createComponent({ editor }) {
|
|
24
|
+
return shallowMount(StylePresetControl, {
|
|
25
|
+
provide: { [InjectionTokens.EDITOR]: editor }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe('rendering', () => {
|
|
30
|
+
test('should render dropdown options', () => {
|
|
31
|
+
const editor = createEditor({
|
|
32
|
+
presets: [
|
|
33
|
+
{ id: 'h1', name: 'H1' },
|
|
34
|
+
{ id: 'regular-1', name: 'Regular 1' }
|
|
35
|
+
]
|
|
36
|
+
});
|
|
37
|
+
const wrapper = createComponent({ editor });
|
|
38
|
+
const dropdownWrapper = wrapper.findComponent(Dropdown);
|
|
39
|
+
|
|
40
|
+
expect(dropdownWrapper.props('options')).toEqual([
|
|
41
|
+
{ id: 'h1', title: 'H1' },
|
|
42
|
+
{ id: 'regular-1', title: 'Regular 1' }
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('should render preset from selection', () => {
|
|
47
|
+
const editor = createEditor({
|
|
48
|
+
presets: [{ id: 'regular-1', name: 'Regular 1' }],
|
|
49
|
+
preset: { id: 'regular-1' }
|
|
50
|
+
});
|
|
51
|
+
const wrapper = createComponent({ editor });
|
|
52
|
+
const dropdownWrapper = wrapper.findComponent(Dropdown);
|
|
53
|
+
|
|
54
|
+
expect(dropdownWrapper.props('value')).toBe('regular-1');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('should disable reset if no customization', () => {
|
|
58
|
+
const editor = createEditor({
|
|
59
|
+
customization: { marks: [], attributes: [] }
|
|
60
|
+
});
|
|
61
|
+
const wrapper = createComponent({ editor });
|
|
62
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
63
|
+
|
|
64
|
+
expect(buttonWrapper.props('disabled')).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('should enable reset if marks customized', () => {
|
|
68
|
+
const editor = createEditor({
|
|
69
|
+
customization: {
|
|
70
|
+
marks: ['font_size'],
|
|
71
|
+
attributes: []
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const wrapper = createComponent({ editor });
|
|
75
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
76
|
+
|
|
77
|
+
expect(buttonWrapper.props('disabled')).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('should enable reset if attributes customized', () => {
|
|
81
|
+
const editor = createEditor({
|
|
82
|
+
customization: {
|
|
83
|
+
marks: [],
|
|
84
|
+
attributes: ['alignment']
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const wrapper = createComponent({ editor });
|
|
88
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
89
|
+
|
|
90
|
+
expect(buttonWrapper.props('disabled')).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('should enable reset if attributes and marks customized', () => {
|
|
94
|
+
const editor = createEditor({
|
|
95
|
+
customization: {
|
|
96
|
+
marks: ['font_size'],
|
|
97
|
+
attributes: ['alignment']
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const wrapper = createComponent({ editor });
|
|
101
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
102
|
+
|
|
103
|
+
expect(buttonWrapper.props('disabled')).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('apply preset', () => {
|
|
108
|
+
test('should apply preset to text', () => {
|
|
109
|
+
const editor = createEditor();
|
|
110
|
+
const wrapper = createComponent({ editor });
|
|
111
|
+
const dropdownWrapper = wrapper.findComponent(Dropdown);
|
|
112
|
+
|
|
113
|
+
dropdownWrapper.vm.$emit('change', 'regular-1');
|
|
114
|
+
|
|
115
|
+
expect(editor.commands.applyPreset).toHaveBeenCalledWith('regular-1');
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('remove customization', () => {
|
|
120
|
+
test('should remove preset customization text', () => {
|
|
121
|
+
const editor = createEditor();
|
|
122
|
+
const wrapper = createComponent({ editor });
|
|
123
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
124
|
+
|
|
125
|
+
buttonWrapper.vm.$emit('click');
|
|
126
|
+
|
|
127
|
+
expect(editor.commands.removePresetCustomization).toHaveBeenCalled();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import { InjectionTokens } from '../../../../injectionTokens';
|
|
3
|
+
import { Button } from '../../../base';
|
|
4
|
+
import SuperscriptControl from '../SuperscriptControl';
|
|
5
|
+
|
|
6
|
+
const createEditor = ({ isSuperscript } = {}) => ({
|
|
7
|
+
isActive: () => isSuperscript,
|
|
8
|
+
|
|
9
|
+
commands: {
|
|
10
|
+
focus: jest.fn().mockReturnThis(),
|
|
11
|
+
toggleSuperscript: jest.fn().mockReturnThis(),
|
|
12
|
+
run: jest.fn()
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
chain() {
|
|
16
|
+
return this.commands;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
function createComponent({ editor }) {
|
|
21
|
+
return shallowMount(SuperscriptControl, {
|
|
22
|
+
provide: { [InjectionTokens.EDITOR]: editor }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('selection value', () => {
|
|
27
|
+
test('should render value from selection', () => {
|
|
28
|
+
const editor = createEditor({ isSuperscript: true });
|
|
29
|
+
const wrapper = createComponent({ editor });
|
|
30
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
31
|
+
|
|
32
|
+
expect(buttonWrapper.props('active')).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('should apply new value', () => {
|
|
36
|
+
const editor = createEditor({ isSuperscript: false });
|
|
37
|
+
const wrapper = createComponent({ editor });
|
|
38
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
39
|
+
|
|
40
|
+
buttonWrapper.vm.$emit('click');
|
|
41
|
+
|
|
42
|
+
expect(editor.commands.toggleSuperscript).toHaveBeenCalled();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import { ref } from '@vue/composition-api';
|
|
3
|
+
import { InjectionTokens } from '../../../../injectionTokens';
|
|
4
|
+
import { Button } from '../../../base';
|
|
5
|
+
import UnderlineControl from '../UnderlineControl';
|
|
6
|
+
|
|
7
|
+
const createEditor = ({ isUnderline } = {}) => ({
|
|
8
|
+
commands: {
|
|
9
|
+
isUnderline: () => ref(isUnderline),
|
|
10
|
+
focus: jest.fn().mockReturnThis(),
|
|
11
|
+
toggleUnderline: jest.fn().mockReturnThis(),
|
|
12
|
+
run: jest.fn()
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
chain() {
|
|
16
|
+
return this.commands;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
function createComponent({ editor }) {
|
|
21
|
+
return shallowMount(UnderlineControl, {
|
|
22
|
+
provide: { [InjectionTokens.EDITOR]: editor }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('selection value', () => {
|
|
27
|
+
test('should render value from selection', () => {
|
|
28
|
+
const editor = createEditor({ isUnderline: true });
|
|
29
|
+
const wrapper = createComponent({ editor });
|
|
30
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
31
|
+
|
|
32
|
+
expect(buttonWrapper.props('active')).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('should apply new value', () => {
|
|
36
|
+
const editor = createEditor({ isUnderline: false });
|
|
37
|
+
const wrapper = createComponent({ editor });
|
|
38
|
+
const buttonWrapper = wrapper.findComponent(Button);
|
|
39
|
+
|
|
40
|
+
buttonWrapper.vm.$emit('click');
|
|
41
|
+
|
|
42
|
+
expect(editor.commands.toggleUnderline).toHaveBeenCalled();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { withComponentContext } from '../../../../../__tests__/utils';
|
|
2
|
+
import { InjectionTokens } from '../../../../../injectionTokens';
|
|
3
|
+
import { useRecentFonts } from '../useRecentFonts';
|
|
4
|
+
|
|
5
|
+
const createStorage = (initialData = {}) => ({
|
|
6
|
+
data: initialData,
|
|
7
|
+
|
|
8
|
+
getItem(name) {
|
|
9
|
+
return this.data[name];
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
setItem(name, value) {
|
|
13
|
+
this.data[name] = value;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function createWrapper({ initial } = {}) {
|
|
18
|
+
return withComponentContext(() => {
|
|
19
|
+
return useRecentFonts({ limit: 3 });
|
|
20
|
+
}, {
|
|
21
|
+
provide: {
|
|
22
|
+
[InjectionTokens.LOCAL_STORAGE]: createStorage({
|
|
23
|
+
'wswg.recently_used_fonts': initial
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe('list of fonts', () => {
|
|
30
|
+
test('should get empty', () => {
|
|
31
|
+
const recentFonts = createWrapper();
|
|
32
|
+
|
|
33
|
+
expect(recentFonts.fonts.value).toEqual([]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('should get initial fonts', () => {
|
|
37
|
+
const recentFonts = createWrapper({ initial: ['Lato', 'Roboto'] });
|
|
38
|
+
|
|
39
|
+
expect(recentFonts.fonts.value).toEqual(['Lato', 'Roboto']);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('should add font', () => {
|
|
43
|
+
const recentFonts = createWrapper();
|
|
44
|
+
|
|
45
|
+
recentFonts.add('Lato');
|
|
46
|
+
|
|
47
|
+
expect(recentFonts.fonts.value).toEqual(['Lato']);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('should move up font in list', () => {
|
|
51
|
+
const recentFonts = createWrapper({
|
|
52
|
+
initial: ['Roboto', 'Source Sans', 'Lato']
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
recentFonts.add('Lato');
|
|
56
|
+
|
|
57
|
+
expect(recentFonts.fonts.value).toEqual(['Lato', 'Roboto', 'Source Sans']);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('should move up font in list', () => {
|
|
61
|
+
const recentFonts = createWrapper({
|
|
62
|
+
initial: ['Roboto', 'Source Sans', 'Times New Roman']
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
recentFonts.add('Lato');
|
|
66
|
+
|
|
67
|
+
expect(recentFonts.fonts.value).toEqual(['Lato', 'Roboto', 'Source Sans']);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useRecentFonts } from './useRecentFonts';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { computed, inject, ref } from '@vue/composition-api';
|
|
2
|
+
import { InjectionTokens } from '../../../../injectionTokens';
|
|
3
|
+
|
|
4
|
+
const STORAGE_KEY = 'wswg.recently_used_fonts';
|
|
5
|
+
|
|
6
|
+
export function useRecentFonts({ limit }) {
|
|
7
|
+
const localStorage = inject(InjectionTokens.LOCAL_STORAGE);
|
|
8
|
+
const fonts = ref(localStorage.getItem(STORAGE_KEY) || []);
|
|
9
|
+
|
|
10
|
+
function add(font) {
|
|
11
|
+
fonts.value = Array.from(new Set([font, ...fonts.value])).slice(0, limit);
|
|
12
|
+
localStorage.setItem(STORAGE_KEY, fonts.value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const isEmpty = computed(() => !fonts.value.length);
|
|
16
|
+
|
|
17
|
+
return { fonts, isEmpty, add };
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { default as StylePresetControl } from './StylePresetControl';
|
|
2
|
+
export { default as FontFamilyControl } from './FontFamilyControl';
|
|
3
|
+
export { default as FontWeightControl } from './FontWeightControl';
|
|
4
|
+
export { default as FontSizeControl } from './FontSizeControl';
|
|
5
|
+
export { default as FontColorControl } from './FontColorControl';
|
|
6
|
+
export { default as BackgroundColorControl } from './BackgroundColorControl';
|
|
7
|
+
export { default as ItalicControl } from './ItalicControl';
|
|
8
|
+
export { default as UnderlineControl } from './UnderlineControl';
|
|
9
|
+
export { default as StrikeThroughControl } from './StrikeThroughControl';
|
|
10
|
+
export { default as SuperscriptControl } from './SuperscriptControl';
|
|
11
|
+
export { default as CaseStyleControl } from './CaseStyleControl';
|
|
12
|
+
export { default as AlignmentControl } from './AlignmentControl';
|
|
13
|
+
export { default as AlignmentDeviceControl } from './AlignmentDeviceControl';
|
|
14
|
+
export { default as LineHeightControl } from './LineHeightControl';
|
|
15
|
+
export { default as ListControl } from './ListControl';
|
|
16
|
+
export { default as RemoveFormatControl } from './RemoveFormatControl';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Toolbar } from './Toolbar';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`life cycle should emit changes 1`] = `
|
|
4
|
+
Array [
|
|
5
|
+
Array [
|
|
6
|
+
Object {
|
|
7
|
+
"content": Array [
|
|
8
|
+
Object {
|
|
9
|
+
"content": Array [
|
|
10
|
+
Object {
|
|
11
|
+
"text": "updated",
|
|
12
|
+
"type": "text",
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
"type": "paragraph",
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
"type": "doc",
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
]
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
exports[`life cycle should mount editor 1`] = `"<p class=\\"zw-style\\">test</p>"`;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { h, toRef } from '@vue/composition-api';
|
|
2
|
+
import { EditorContent } from '@tiptap/vue-2';
|
|
3
|
+
import { shallowMount } from '@vue/test-utils';
|
|
4
|
+
import { CORE_EXTENSIONS } from '../../extensions';
|
|
5
|
+
import { useEditor } from '../useEditor';
|
|
6
|
+
import { NodeFactory } from '../../__tests__/utils';
|
|
7
|
+
|
|
8
|
+
const TestComponent = {
|
|
9
|
+
name: 'Test',
|
|
10
|
+
render() {
|
|
11
|
+
return h(EditorContent, {
|
|
12
|
+
props: { editor: this.editor }
|
|
13
|
+
});
|
|
14
|
+
},
|
|
15
|
+
props: ['value'],
|
|
16
|
+
|
|
17
|
+
setup(props, { emit }) {
|
|
18
|
+
const editor = useEditor({
|
|
19
|
+
content: toRef(props, 'value'),
|
|
20
|
+
extensions: CORE_EXTENSIONS,
|
|
21
|
+
onChange: (content) => {
|
|
22
|
+
emit('input', content);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return { editor };
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const createContent = (text = 'test') => NodeFactory.doc([
|
|
31
|
+
NodeFactory.paragraph(text)
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
function createComponent({ content } = {}) {
|
|
35
|
+
const wrapper = shallowMount(TestComponent, {
|
|
36
|
+
propsData: { value: content || createContent('test') }
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
wrapper,
|
|
41
|
+
editor: wrapper.vm.editor
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe('life cycle', () => {
|
|
46
|
+
test('should mount editor', () => {
|
|
47
|
+
const { editor } = createComponent();
|
|
48
|
+
|
|
49
|
+
expect(editor.getHTML()).toMatchSnapshot();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('should emit changes', () => {
|
|
53
|
+
const { wrapper, editor } = createComponent();
|
|
54
|
+
|
|
55
|
+
editor.commands.setContent('<p>updated</p>', true);
|
|
56
|
+
|
|
57
|
+
expect(wrapper.emitted('input')).toMatchSnapshot();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('should destroy editor', () => {
|
|
61
|
+
const { wrapper, editor } = createComponent();
|
|
62
|
+
|
|
63
|
+
wrapper.destroy();
|
|
64
|
+
|
|
65
|
+
expect(editor.isDestroyed).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createPopper } from '@popperjs/core';
|
|
2
|
+
import { ref, nextTick } from '@vue/composition-api';
|
|
3
|
+
import { withComponentContext } from '../../__tests__/utils';
|
|
4
|
+
import { useToolbar } from '../useToolbar';
|
|
5
|
+
import { useElementRef } from '../../components/base/composables';
|
|
6
|
+
|
|
7
|
+
jest.mock('@popperjs/core', () => ({
|
|
8
|
+
createPopper: jest.fn(() => ({
|
|
9
|
+
update: jest.fn()
|
|
10
|
+
}))
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
function createWrapper() {
|
|
14
|
+
const el = document.createElement('div');
|
|
15
|
+
const elementRef = useElementRef(ref(el));
|
|
16
|
+
|
|
17
|
+
return withComponentContext(() => {
|
|
18
|
+
return useToolbar({
|
|
19
|
+
wrapperRef: elementRef,
|
|
20
|
+
popperRef: elementRef
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('manage opened state', () => {
|
|
26
|
+
test('should show toolbar', () => {
|
|
27
|
+
const toolbarComponent = createWrapper();
|
|
28
|
+
|
|
29
|
+
toolbarComponent.show();
|
|
30
|
+
|
|
31
|
+
expect(toolbarComponent.isShow.value).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('should hide toolbar', () => {
|
|
35
|
+
const toolbarComponent = createWrapper();
|
|
36
|
+
|
|
37
|
+
toolbarComponent.show();
|
|
38
|
+
toolbarComponent.hide();
|
|
39
|
+
|
|
40
|
+
expect(toolbarComponent.isShow.value).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('should update toolbar on open', async () => {
|
|
44
|
+
const popper = { update: jest.fn() };
|
|
45
|
+
|
|
46
|
+
createPopper.mockReturnValueOnce(popper);
|
|
47
|
+
|
|
48
|
+
const toolbarComponent = createWrapper();
|
|
49
|
+
|
|
50
|
+
await nextTick();
|
|
51
|
+
|
|
52
|
+
toolbarComponent.show();
|
|
53
|
+
|
|
54
|
+
expect(popper.update).toHaveBeenCalled();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/vue-2';
|
|
2
|
+
import { onUnmounted, watch } from '@vue/composition-api';
|
|
3
|
+
|
|
4
|
+
export function useEditor({ content, onChange, onFocus, extensions }) {
|
|
5
|
+
const editor = new Editor({
|
|
6
|
+
content: content.value,
|
|
7
|
+
onUpdate: () => onChange(editor.getJSON()),
|
|
8
|
+
onFocus: () => onFocus(),
|
|
9
|
+
extensions
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
onUnmounted(() => editor.destroy());
|
|
13
|
+
|
|
14
|
+
watch(content, (value) => {
|
|
15
|
+
const isChanged = JSON.stringify(editor.getJSON()) !== JSON.stringify(value);
|
|
16
|
+
|
|
17
|
+
if (isChanged) editor.commands.setContent(value, false);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return editor;
|
|
21
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createPopper } from '@popperjs/core';
|
|
2
|
+
import { onUnmounted, onMounted, ref } from '@vue/composition-api';
|
|
3
|
+
import { useElementRef } from '../components/base/composables';
|
|
4
|
+
|
|
5
|
+
export function useToolbar({ wrapperRef, popperRef, offsets }) {
|
|
6
|
+
let toolbar;
|
|
7
|
+
const isShow = ref(false);
|
|
8
|
+
|
|
9
|
+
onMounted(() => {
|
|
10
|
+
const wrapperEl = useElementRef(wrapperRef).value;
|
|
11
|
+
const toolbarEl = useElementRef(popperRef).value;
|
|
12
|
+
|
|
13
|
+
toolbar = createPopper(wrapperEl, toolbarEl, {
|
|
14
|
+
placement: 'top-start',
|
|
15
|
+
modifiers: [
|
|
16
|
+
{
|
|
17
|
+
name: 'offset',
|
|
18
|
+
options: {
|
|
19
|
+
offset: offsets
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
onUnmounted(() => {
|
|
27
|
+
toolbar.destroy();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function hide() {
|
|
31
|
+
isShow.value = false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function show() {
|
|
35
|
+
isShow.value = true;
|
|
36
|
+
this.update();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function update() {
|
|
40
|
+
toolbar.update();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { toolbar, show, hide, update, isShow };
|
|
44
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { waitAsyncOperation } from '../../__tests__/utils';
|
|
2
|
+
import { outClick } from '../outClick';
|
|
3
|
+
|
|
4
|
+
describe('out click', () => {
|
|
5
|
+
test('should trigger on out click', async () => {
|
|
6
|
+
const el = document.createElement('div');
|
|
7
|
+
const onOutClick = jest.fn();
|
|
8
|
+
|
|
9
|
+
outClick.bind(el, { value: onOutClick });
|
|
10
|
+
await waitAsyncOperation();
|
|
11
|
+
|
|
12
|
+
document.dispatchEvent(new Event('click'));
|
|
13
|
+
|
|
14
|
+
expect(onOutClick).toHaveBeenCalled();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('should not trigger on element click', async () => {
|
|
18
|
+
const el = document.createElement('div');
|
|
19
|
+
const onOutClick = jest.fn();
|
|
20
|
+
|
|
21
|
+
outClick.bind(el, { value: onOutClick });
|
|
22
|
+
await waitAsyncOperation();
|
|
23
|
+
|
|
24
|
+
el.dispatchEvent(new Event('click'));
|
|
25
|
+
|
|
26
|
+
expect(onOutClick).not.toHaveBeenCalled();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('should not trigger on child element click', async () => {
|
|
30
|
+
const el = document.createElement('div');
|
|
31
|
+
const child = document.createElement('div');
|
|
32
|
+
const onOutClick = jest.fn();
|
|
33
|
+
|
|
34
|
+
el.append(child);
|
|
35
|
+
outClick.bind(el, { value: onOutClick });
|
|
36
|
+
await waitAsyncOperation();
|
|
37
|
+
|
|
38
|
+
child.dispatchEvent(new Event('click'));
|
|
39
|
+
|
|
40
|
+
expect(onOutClick).not.toHaveBeenCalled();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('should remove out click listener', async () => {
|
|
44
|
+
const el = document.createElement('div');
|
|
45
|
+
const onOutClick = jest.fn();
|
|
46
|
+
|
|
47
|
+
outClick.bind(el, { value: onOutClick });
|
|
48
|
+
await waitAsyncOperation();
|
|
49
|
+
|
|
50
|
+
outClick.unbind(el);
|
|
51
|
+
|
|
52
|
+
document.dispatchEvent(new Event('click'));
|
|
53
|
+
|
|
54
|
+
expect(onOutClick).not.toHaveBeenCalled();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('should add listener on update', async () => {
|
|
58
|
+
const el = document.createElement('div');
|
|
59
|
+
const onOutClick = jest.fn();
|
|
60
|
+
|
|
61
|
+
outClick.bind(el, { value: { onOutClick, isDisabled: true } });
|
|
62
|
+
await waitAsyncOperation();
|
|
63
|
+
|
|
64
|
+
outClick.update(el, { value: { isDisabled: false } });
|
|
65
|
+
await waitAsyncOperation();
|
|
66
|
+
|
|
67
|
+
document.dispatchEvent(new Event('click'));
|
|
68
|
+
|
|
69
|
+
expect(onOutClick).toHaveBeenCalled();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('should remove listener on update', async () => {
|
|
73
|
+
const el = document.createElement('div');
|
|
74
|
+
const onOutClick = jest.fn();
|
|
75
|
+
|
|
76
|
+
outClick.bind(el, { value: { onOutClick, isDisabled: false } });
|
|
77
|
+
await waitAsyncOperation();
|
|
78
|
+
|
|
79
|
+
outClick.update(el, { value: { isDisabled: true } });
|
|
80
|
+
await waitAsyncOperation();
|
|
81
|
+
|
|
82
|
+
document.dispatchEvent(new Event('click'));
|
|
83
|
+
|
|
84
|
+
expect(onOutClick).not.toHaveBeenCalled();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { tooltip } from '../tooltip';
|
|
2
|
+
|
|
3
|
+
describe('rendering', () => {
|
|
4
|
+
test('should render text only tooltip', () => {
|
|
5
|
+
const el = document.createElement('div');
|
|
6
|
+
|
|
7
|
+
tooltip(el, { value: 'Test' });
|
|
8
|
+
|
|
9
|
+
expect(el.dataset.tooltip).toBe('Test');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('should render text only in object mode', () => {
|
|
13
|
+
const el = document.createElement('div');
|
|
14
|
+
|
|
15
|
+
tooltip(el, {
|
|
16
|
+
value: { text: 'Test' }
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
expect(el.dataset.tooltip).toBe('Test');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('should render with hotkey', () => {
|
|
23
|
+
const el = document.createElement('div');
|
|
24
|
+
|
|
25
|
+
tooltip(el, {
|
|
26
|
+
value: { text: 'Test', hotkey: 'Mod B' }
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
expect(el.dataset.tooltipHotkey).toBe('Mod B');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('should not render tooltip if no value passed', () => {
|
|
33
|
+
const el = document.createElement('div');
|
|
34
|
+
|
|
35
|
+
tooltip(el, { value: '' });
|
|
36
|
+
|
|
37
|
+
expect(el.dataset).not.toHaveProperty('tooltip');
|
|
38
|
+
});
|
|
39
|
+
});
|