kempo-ui 0.3.9 → 0.3.10
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/package.json +3 -3
- package/tests/components/htmlEditorControls/Align.browser-test.js +203 -0
- package/tests/components/htmlEditorControls/Bold.browser-test.js +127 -0
- package/tests/components/htmlEditorControls/BulletList.browser-test.js +127 -0
- package/tests/components/htmlEditorControls/CharacterCount.browser-test.js +106 -0
- package/tests/components/htmlEditorControls/ClearFormatting.browser-test.js +127 -0
- package/tests/components/htmlEditorControls/CodeBlock.browser-test.js +143 -0
- package/tests/components/htmlEditorControls/ControlGroup.browser-test.js +116 -0
- package/tests/components/htmlEditorControls/ControlSpacer.browser-test.js +69 -0
- package/tests/components/htmlEditorControls/CreateLink.browser-test.js +129 -0
- package/tests/components/htmlEditorControls/DropdownControl.browser-test.js +138 -0
- package/tests/components/htmlEditorControls/FormatBlock.browser-test.js +163 -0
- package/tests/components/htmlEditorControls/InlineCode.browser-test.js +127 -0
- package/tests/components/htmlEditorControls/InsertTable.browser-test.js +129 -0
- package/tests/components/htmlEditorControls/Italic.browser-test.js +127 -0
- package/tests/components/htmlEditorControls/Mode.browser-test.js +138 -0
- package/tests/components/htmlEditorControls/NumberList.browser-test.js +127 -0
- package/tests/components/htmlEditorControls/Strikethrough.browser-test.js +127 -0
- package/tests/components/htmlEditorControls/TextBackgroundColor.browser-test.js +136 -0
- package/tests/components/htmlEditorControls/TextColor.browser-test.js +136 -0
- package/tests/components/htmlEditorControls/Underline.browser-test.js +127 -0
- package/tests/components/htmlEditorControls/WordCount.browser-test.js +106 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import '../../../src/components/HtmlEditor.js';
|
|
2
|
+
import ClearFormatting from '../../../src/components/htmlEditorControls/ClearFormatting.js';
|
|
3
|
+
|
|
4
|
+
const createEditorWithControl = async () => {
|
|
5
|
+
const container = document.createElement('div');
|
|
6
|
+
container.innerHTML = `
|
|
7
|
+
<k-html-editor>
|
|
8
|
+
<k-hec-clear-formatting slot="toolbar-top-left"></k-hec-clear-formatting>
|
|
9
|
+
</k-html-editor>
|
|
10
|
+
`;
|
|
11
|
+
document.body.appendChild(container);
|
|
12
|
+
const editor = container.querySelector('k-html-editor');
|
|
13
|
+
await new Promise(r => editor.addEventListener('ready', r, { once: true }));
|
|
14
|
+
const control = container.querySelector('k-hec-clear-formatting');
|
|
15
|
+
return { container, editor, control };
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const cleanup = container => {
|
|
19
|
+
if(container?.parentNode) container.parentNode.removeChild(container);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
/*
|
|
24
|
+
Element Creation
|
|
25
|
+
*/
|
|
26
|
+
'should create k-hec-clear-formatting element': async ({pass, fail}) => {
|
|
27
|
+
const { container, control } = await createEditorWithControl();
|
|
28
|
+
if(!(control instanceof ClearFormatting)){
|
|
29
|
+
cleanup(container);
|
|
30
|
+
return fail('Element should be instance of ClearFormatting');
|
|
31
|
+
}
|
|
32
|
+
cleanup(container);
|
|
33
|
+
pass('ClearFormatting element created correctly');
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
'should have shadow root': async ({pass, fail}) => {
|
|
37
|
+
const { container, control } = await createEditorWithControl();
|
|
38
|
+
if(!control.shadowRoot){
|
|
39
|
+
cleanup(container);
|
|
40
|
+
return fail('ClearFormatting should have shadow root');
|
|
41
|
+
}
|
|
42
|
+
cleanup(container);
|
|
43
|
+
pass('ClearFormatting has shadow root');
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
'should render a button': async ({pass, fail}) => {
|
|
47
|
+
const { container, control } = await createEditorWithControl();
|
|
48
|
+
await control.updateComplete;
|
|
49
|
+
const button = control.shadowRoot.querySelector('button');
|
|
50
|
+
if(!button){
|
|
51
|
+
cleanup(container);
|
|
52
|
+
return fail('ClearFormatting should render a button');
|
|
53
|
+
}
|
|
54
|
+
cleanup(container);
|
|
55
|
+
pass('ClearFormatting renders a button');
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
'should render format_clear icon': async ({pass, fail}) => {
|
|
59
|
+
const { container, control } = await createEditorWithControl();
|
|
60
|
+
await control.updateComplete;
|
|
61
|
+
const icon = control.shadowRoot.querySelector('k-icon');
|
|
62
|
+
if(!icon){
|
|
63
|
+
cleanup(container);
|
|
64
|
+
return fail('ClearFormatting should render a k-icon');
|
|
65
|
+
}
|
|
66
|
+
if(icon.getAttribute('name') !== 'format_clear'){
|
|
67
|
+
cleanup(container);
|
|
68
|
+
return fail(`Expected icon name "format_clear", got "${icon.getAttribute('name')}"`);
|
|
69
|
+
}
|
|
70
|
+
cleanup(container);
|
|
71
|
+
pass('ClearFormatting renders format_clear icon');
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
Editor Integration
|
|
76
|
+
*/
|
|
77
|
+
'should find parent editor': async ({pass, fail}) => {
|
|
78
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
79
|
+
if(control.editor !== editor){
|
|
80
|
+
cleanup(container);
|
|
81
|
+
return fail('ClearFormatting should find its parent k-html-editor');
|
|
82
|
+
}
|
|
83
|
+
cleanup(container);
|
|
84
|
+
pass('ClearFormatting finds parent editor');
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
'click should call editor.removeFormat()': async ({pass, fail}) => {
|
|
88
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
89
|
+
await control.updateComplete;
|
|
90
|
+
let called = false;
|
|
91
|
+
editor.removeFormat = () => { called = true; };
|
|
92
|
+
control.shadowRoot.querySelector('button').click();
|
|
93
|
+
if(!called){
|
|
94
|
+
cleanup(container);
|
|
95
|
+
return fail('Click should call editor.removeFormat()');
|
|
96
|
+
}
|
|
97
|
+
cleanup(container);
|
|
98
|
+
pass('Click calls editor.removeFormat()');
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
Code Mode Visibility
|
|
103
|
+
*/
|
|
104
|
+
'should hide in code mode': async ({pass, fail}) => {
|
|
105
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
106
|
+
editor.setMode('code');
|
|
107
|
+
await new Promise(r => editor.addEventListener('mode-changed', r, { once: true }));
|
|
108
|
+
await control.updateComplete;
|
|
109
|
+
if(!control.hidden){
|
|
110
|
+
cleanup(container);
|
|
111
|
+
return fail('ClearFormatting should be hidden in code mode');
|
|
112
|
+
}
|
|
113
|
+
cleanup(container);
|
|
114
|
+
pass('ClearFormatting is hidden in code mode');
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
'should be visible in visual mode': async ({pass, fail}) => {
|
|
118
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
119
|
+
await control.updateComplete;
|
|
120
|
+
if(control.hidden){
|
|
121
|
+
cleanup(container);
|
|
122
|
+
return fail('ClearFormatting should be visible in visual mode');
|
|
123
|
+
}
|
|
124
|
+
cleanup(container);
|
|
125
|
+
pass('ClearFormatting is visible in visual mode');
|
|
126
|
+
},
|
|
127
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import '../../../src/components/HtmlEditor.js';
|
|
2
|
+
import CodeBlock from '../../../src/components/htmlEditorControls/CodeBlock.js';
|
|
3
|
+
|
|
4
|
+
const createEditorWithControl = async () => {
|
|
5
|
+
const container = document.createElement('div');
|
|
6
|
+
container.innerHTML = `
|
|
7
|
+
<k-html-editor>
|
|
8
|
+
<k-hec-code-block slot="toolbar-top-left"></k-hec-code-block>
|
|
9
|
+
</k-html-editor>
|
|
10
|
+
`;
|
|
11
|
+
document.body.appendChild(container);
|
|
12
|
+
const editor = container.querySelector('k-html-editor');
|
|
13
|
+
await new Promise(r => editor.addEventListener('ready', r, { once: true }));
|
|
14
|
+
const control = container.querySelector('k-hec-code-block');
|
|
15
|
+
return { container, editor, control };
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const cleanup = container => {
|
|
19
|
+
if(container?.parentNode) container.parentNode.removeChild(container);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
/*
|
|
24
|
+
Element Creation
|
|
25
|
+
*/
|
|
26
|
+
'should create k-hec-code-block element': async ({pass, fail}) => {
|
|
27
|
+
const { container, control } = await createEditorWithControl();
|
|
28
|
+
if(!(control instanceof CodeBlock)){
|
|
29
|
+
cleanup(container);
|
|
30
|
+
return fail('Element should be instance of CodeBlock');
|
|
31
|
+
}
|
|
32
|
+
cleanup(container);
|
|
33
|
+
pass('CodeBlock element created correctly');
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
'should have shadow root': async ({pass, fail}) => {
|
|
37
|
+
const { container, control } = await createEditorWithControl();
|
|
38
|
+
if(!control.shadowRoot){
|
|
39
|
+
cleanup(container);
|
|
40
|
+
return fail('CodeBlock should have shadow root');
|
|
41
|
+
}
|
|
42
|
+
cleanup(container);
|
|
43
|
+
pass('CodeBlock has shadow root');
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
'should render a button': async ({pass, fail}) => {
|
|
47
|
+
const { container, control } = await createEditorWithControl();
|
|
48
|
+
await control.updateComplete;
|
|
49
|
+
const button = control.shadowRoot.querySelector('button');
|
|
50
|
+
if(!button){
|
|
51
|
+
cleanup(container);
|
|
52
|
+
return fail('CodeBlock should render a button');
|
|
53
|
+
}
|
|
54
|
+
cleanup(container);
|
|
55
|
+
pass('CodeBlock renders a button');
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
'should render code_blocks icon': async ({pass, fail}) => {
|
|
59
|
+
const { container, control } = await createEditorWithControl();
|
|
60
|
+
await control.updateComplete;
|
|
61
|
+
const icon = control.shadowRoot.querySelector('k-icon');
|
|
62
|
+
if(!icon){
|
|
63
|
+
cleanup(container);
|
|
64
|
+
return fail('CodeBlock should render a k-icon');
|
|
65
|
+
}
|
|
66
|
+
if(icon.getAttribute('name') !== 'code_blocks'){
|
|
67
|
+
cleanup(container);
|
|
68
|
+
return fail(`Expected icon name "code_blocks", got "${icon.getAttribute('name')}"`);
|
|
69
|
+
}
|
|
70
|
+
cleanup(container);
|
|
71
|
+
pass('CodeBlock renders code_blocks icon');
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
Editor Integration
|
|
76
|
+
*/
|
|
77
|
+
'should find parent editor': async ({pass, fail}) => {
|
|
78
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
79
|
+
if(control.editor !== editor){
|
|
80
|
+
cleanup(container);
|
|
81
|
+
return fail('CodeBlock should find its parent k-html-editor');
|
|
82
|
+
}
|
|
83
|
+
cleanup(container);
|
|
84
|
+
pass('CodeBlock finds parent editor');
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
'click should call editor.formatBlock when not in code block': async ({pass, fail}) => {
|
|
88
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
89
|
+
await control.updateComplete;
|
|
90
|
+
let calledWith = null;
|
|
91
|
+
editor.isSelectionInCodeBlock = () => false;
|
|
92
|
+
editor.formatBlock = tag => { calledWith = tag; };
|
|
93
|
+
control.shadowRoot.querySelector('button').click();
|
|
94
|
+
if(calledWith !== 'pre'){
|
|
95
|
+
cleanup(container);
|
|
96
|
+
return fail(`Expected formatBlock("pre"), got formatBlock("${calledWith}")`);
|
|
97
|
+
}
|
|
98
|
+
cleanup(container);
|
|
99
|
+
pass('Click calls editor.formatBlock("pre") when not in code block');
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
'click should call editor.formatBlock("p") when in code block': async ({pass, fail}) => {
|
|
103
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
104
|
+
await control.updateComplete;
|
|
105
|
+
let calledWith = null;
|
|
106
|
+
editor.isSelectionInCodeBlock = () => true;
|
|
107
|
+
editor.formatBlock = tag => { calledWith = tag; };
|
|
108
|
+
control.shadowRoot.querySelector('button').click();
|
|
109
|
+
if(calledWith !== 'p'){
|
|
110
|
+
cleanup(container);
|
|
111
|
+
return fail(`Expected formatBlock("p"), got formatBlock("${calledWith}")`);
|
|
112
|
+
}
|
|
113
|
+
cleanup(container);
|
|
114
|
+
pass('Click calls editor.formatBlock("p") when in code block');
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
Code Mode Visibility
|
|
119
|
+
*/
|
|
120
|
+
'should hide in code mode': async ({pass, fail}) => {
|
|
121
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
122
|
+
editor.setMode('code');
|
|
123
|
+
await new Promise(r => editor.addEventListener('mode-changed', r, { once: true }));
|
|
124
|
+
await control.updateComplete;
|
|
125
|
+
if(!control.hidden){
|
|
126
|
+
cleanup(container);
|
|
127
|
+
return fail('CodeBlock should be hidden in code mode');
|
|
128
|
+
}
|
|
129
|
+
cleanup(container);
|
|
130
|
+
pass('CodeBlock is hidden in code mode');
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
'should be visible in visual mode': async ({pass, fail}) => {
|
|
134
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
135
|
+
await control.updateComplete;
|
|
136
|
+
if(control.hidden){
|
|
137
|
+
cleanup(container);
|
|
138
|
+
return fail('CodeBlock should be visible in visual mode');
|
|
139
|
+
}
|
|
140
|
+
cleanup(container);
|
|
141
|
+
pass('CodeBlock is visible in visual mode');
|
|
142
|
+
},
|
|
143
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import '../../../src/components/HtmlEditor.js';
|
|
2
|
+
import ControlGroup from '../../../src/components/htmlEditorControls/ControlGroup.js';
|
|
3
|
+
import '../../../src/components/htmlEditorControls/Bold.js';
|
|
4
|
+
import '../../../src/components/htmlEditorControls/Italic.js';
|
|
5
|
+
|
|
6
|
+
const createEditorWithGroup = async () => {
|
|
7
|
+
const container = document.createElement('div');
|
|
8
|
+
container.innerHTML = `
|
|
9
|
+
<k-html-editor>
|
|
10
|
+
<k-hec-group slot="toolbar-top-left">
|
|
11
|
+
<k-hec-bold></k-hec-bold>
|
|
12
|
+
<k-hec-italic></k-hec-italic>
|
|
13
|
+
</k-hec-group>
|
|
14
|
+
</k-html-editor>
|
|
15
|
+
`;
|
|
16
|
+
document.body.appendChild(container);
|
|
17
|
+
const editor = container.querySelector('k-html-editor');
|
|
18
|
+
await new Promise(r => editor.addEventListener('ready', r, { once: true }));
|
|
19
|
+
const group = container.querySelector('k-hec-group');
|
|
20
|
+
return { container, editor, group };
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const cleanup = container => {
|
|
24
|
+
if(container?.parentNode) container.parentNode.removeChild(container);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
/*
|
|
29
|
+
Element Creation
|
|
30
|
+
*/
|
|
31
|
+
'should create k-hec-group element': async ({pass, fail}) => {
|
|
32
|
+
const { container, group } = await createEditorWithGroup();
|
|
33
|
+
if(!(group instanceof ControlGroup)){
|
|
34
|
+
cleanup(container);
|
|
35
|
+
return fail('Element should be instance of ControlGroup');
|
|
36
|
+
}
|
|
37
|
+
cleanup(container);
|
|
38
|
+
pass('ControlGroup element created correctly');
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
'should have shadow root': async ({pass, fail}) => {
|
|
42
|
+
const { container, group } = await createEditorWithGroup();
|
|
43
|
+
if(!group.shadowRoot){
|
|
44
|
+
cleanup(container);
|
|
45
|
+
return fail('ControlGroup should have shadow root');
|
|
46
|
+
}
|
|
47
|
+
cleanup(container);
|
|
48
|
+
pass('ControlGroup has shadow root');
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
'should render a slot': async ({pass, fail}) => {
|
|
52
|
+
const { container, group } = await createEditorWithGroup();
|
|
53
|
+
await group.updateComplete;
|
|
54
|
+
const slot = group.shadowRoot.querySelector('slot');
|
|
55
|
+
if(!slot){
|
|
56
|
+
cleanup(container);
|
|
57
|
+
return fail('ControlGroup should render a slot');
|
|
58
|
+
}
|
|
59
|
+
cleanup(container);
|
|
60
|
+
pass('ControlGroup renders a slot');
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
Visibility
|
|
65
|
+
*/
|
|
66
|
+
'should default to not hidden': async ({pass, fail}) => {
|
|
67
|
+
const { container, group } = await createEditorWithGroup();
|
|
68
|
+
if(group.hidden){
|
|
69
|
+
cleanup(container);
|
|
70
|
+
return fail('ControlGroup should not be hidden by default');
|
|
71
|
+
}
|
|
72
|
+
cleanup(container);
|
|
73
|
+
pass('ControlGroup is not hidden by default');
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
'should hide when all children are hidden': async ({pass, fail}) => {
|
|
77
|
+
const { container, group } = await createEditorWithGroup();
|
|
78
|
+
const children = Array.from(group.children);
|
|
79
|
+
children.forEach(child => { child.hidden = true; });
|
|
80
|
+
group.checkVisibility(new CustomEvent('control_visibility_change'));
|
|
81
|
+
if(!group.hidden){
|
|
82
|
+
cleanup(container);
|
|
83
|
+
return fail('ControlGroup should hide when all children are hidden');
|
|
84
|
+
}
|
|
85
|
+
cleanup(container);
|
|
86
|
+
pass('ControlGroup hides when all children are hidden');
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
'should show when at least one child is visible': async ({pass, fail}) => {
|
|
90
|
+
const { container, group } = await createEditorWithGroup();
|
|
91
|
+
const children = Array.from(group.children);
|
|
92
|
+
children[0].hidden = true;
|
|
93
|
+
children[1].hidden = false;
|
|
94
|
+
group.checkVisibility(new CustomEvent('control_visibility_change'));
|
|
95
|
+
if(group.hidden){
|
|
96
|
+
cleanup(container);
|
|
97
|
+
return fail('ControlGroup should be visible when at least one child is visible');
|
|
98
|
+
}
|
|
99
|
+
cleanup(container);
|
|
100
|
+
pass('ControlGroup is visible when at least one child is visible');
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
Class Attribute
|
|
105
|
+
*/
|
|
106
|
+
'should set default class attribute': async ({pass, fail}) => {
|
|
107
|
+
const { container, group } = await createEditorWithGroup();
|
|
108
|
+
const cls = group.getAttribute('class');
|
|
109
|
+
if(!cls || !cls.includes('b')){
|
|
110
|
+
cleanup(container);
|
|
111
|
+
return fail(`Expected default class containing "b", got "${cls}"`);
|
|
112
|
+
}
|
|
113
|
+
cleanup(container);
|
|
114
|
+
pass('ControlGroup sets default class attribute');
|
|
115
|
+
},
|
|
116
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import '../../../src/components/HtmlEditor.js';
|
|
2
|
+
import ControlSpacer from '../../../src/components/htmlEditorControls/ControlSpacer.js';
|
|
3
|
+
|
|
4
|
+
const createEditorWithControl = async () => {
|
|
5
|
+
const container = document.createElement('div');
|
|
6
|
+
container.innerHTML = `
|
|
7
|
+
<k-html-editor>
|
|
8
|
+
<k-hec-spacer slot="toolbar-top-left"></k-hec-spacer>
|
|
9
|
+
</k-html-editor>
|
|
10
|
+
`;
|
|
11
|
+
document.body.appendChild(container);
|
|
12
|
+
const editor = container.querySelector('k-html-editor');
|
|
13
|
+
await new Promise(r => editor.addEventListener('ready', r, { once: true }));
|
|
14
|
+
const control = container.querySelector('k-hec-spacer');
|
|
15
|
+
return { container, editor, control };
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const cleanup = container => {
|
|
19
|
+
if(container?.parentNode) container.parentNode.removeChild(container);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
/*
|
|
24
|
+
Element Creation
|
|
25
|
+
*/
|
|
26
|
+
'should create k-hec-spacer element': async ({pass, fail}) => {
|
|
27
|
+
const { container, control } = await createEditorWithControl();
|
|
28
|
+
if(!(control instanceof ControlSpacer)){
|
|
29
|
+
cleanup(container);
|
|
30
|
+
return fail('Element should be instance of ControlSpacer');
|
|
31
|
+
}
|
|
32
|
+
cleanup(container);
|
|
33
|
+
pass('ControlSpacer element created correctly');
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
'should have shadow root': async ({pass, fail}) => {
|
|
37
|
+
const { container, control } = await createEditorWithControl();
|
|
38
|
+
if(!control.shadowRoot){
|
|
39
|
+
cleanup(container);
|
|
40
|
+
return fail('ControlSpacer should have shadow root');
|
|
41
|
+
}
|
|
42
|
+
cleanup(container);
|
|
43
|
+
pass('ControlSpacer has shadow root');
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
'should have flex: 1 style': async ({pass, fail}) => {
|
|
47
|
+
const { container, control } = await createEditorWithControl();
|
|
48
|
+
await control.updateComplete;
|
|
49
|
+
const style = getComputedStyle(control);
|
|
50
|
+
if(style.flexGrow !== '1'){
|
|
51
|
+
cleanup(container);
|
|
52
|
+
return fail(`Expected flex-grow "1", got "${style.flexGrow}"`);
|
|
53
|
+
}
|
|
54
|
+
cleanup(container);
|
|
55
|
+
pass('ControlSpacer has flex: 1 style');
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
'should render no visible elements': async ({pass, fail}) => {
|
|
59
|
+
const { container, control } = await createEditorWithControl();
|
|
60
|
+
await control.updateComplete;
|
|
61
|
+
const buttons = control.shadowRoot.querySelectorAll('button, input, select, textarea, a');
|
|
62
|
+
if(buttons.length > 0){
|
|
63
|
+
cleanup(container);
|
|
64
|
+
return fail('ControlSpacer should not render interactive elements');
|
|
65
|
+
}
|
|
66
|
+
cleanup(container);
|
|
67
|
+
pass('ControlSpacer renders no interactive elements');
|
|
68
|
+
},
|
|
69
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import '../../../src/components/HtmlEditor.js';
|
|
2
|
+
import CreateLink from '../../../src/components/htmlEditorControls/CreateLink.js';
|
|
3
|
+
|
|
4
|
+
const createEditorWithControl = async () => {
|
|
5
|
+
const container = document.createElement('div');
|
|
6
|
+
container.innerHTML = `
|
|
7
|
+
<k-html-editor>
|
|
8
|
+
<k-hec-create-link slot="toolbar-top-left"></k-hec-create-link>
|
|
9
|
+
</k-html-editor>
|
|
10
|
+
`;
|
|
11
|
+
document.body.appendChild(container);
|
|
12
|
+
const editor = container.querySelector('k-html-editor');
|
|
13
|
+
await new Promise(r => editor.addEventListener('ready', r, { once: true }));
|
|
14
|
+
const control = container.querySelector('k-hec-create-link');
|
|
15
|
+
return { container, editor, control };
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const cleanup = container => {
|
|
19
|
+
if(container?.parentNode) container.parentNode.removeChild(container);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
/*
|
|
24
|
+
Element Creation
|
|
25
|
+
*/
|
|
26
|
+
'should create k-hec-create-link element': async ({pass, fail}) => {
|
|
27
|
+
const { container, control } = await createEditorWithControl();
|
|
28
|
+
if(!(control instanceof CreateLink)){
|
|
29
|
+
cleanup(container);
|
|
30
|
+
return fail('Element should be instance of CreateLink');
|
|
31
|
+
}
|
|
32
|
+
cleanup(container);
|
|
33
|
+
pass('CreateLink element created correctly');
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
'should have shadow root': async ({pass, fail}) => {
|
|
37
|
+
const { container, control } = await createEditorWithControl();
|
|
38
|
+
if(!control.shadowRoot){
|
|
39
|
+
cleanup(container);
|
|
40
|
+
return fail('CreateLink should have shadow root');
|
|
41
|
+
}
|
|
42
|
+
cleanup(container);
|
|
43
|
+
pass('CreateLink has shadow root');
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
'should render a button': async ({pass, fail}) => {
|
|
47
|
+
const { container, control } = await createEditorWithControl();
|
|
48
|
+
await control.updateComplete;
|
|
49
|
+
const button = control.shadowRoot.querySelector('button');
|
|
50
|
+
if(!button){
|
|
51
|
+
cleanup(container);
|
|
52
|
+
return fail('CreateLink should render a button');
|
|
53
|
+
}
|
|
54
|
+
cleanup(container);
|
|
55
|
+
pass('CreateLink renders a button');
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
'should render link icon': async ({pass, fail}) => {
|
|
59
|
+
const { container, control } = await createEditorWithControl();
|
|
60
|
+
await control.updateComplete;
|
|
61
|
+
const icon = control.shadowRoot.querySelector('k-icon');
|
|
62
|
+
if(!icon){
|
|
63
|
+
cleanup(container);
|
|
64
|
+
return fail('CreateLink should render a k-icon');
|
|
65
|
+
}
|
|
66
|
+
if(icon.getAttribute('name') !== 'link'){
|
|
67
|
+
cleanup(container);
|
|
68
|
+
return fail(`Expected icon name "link", got "${icon.getAttribute('name')}"`);
|
|
69
|
+
}
|
|
70
|
+
cleanup(container);
|
|
71
|
+
pass('CreateLink renders link icon');
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
Editor Integration
|
|
76
|
+
*/
|
|
77
|
+
'should find parent editor': async ({pass, fail}) => {
|
|
78
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
79
|
+
if(control.editor !== editor){
|
|
80
|
+
cleanup(container);
|
|
81
|
+
return fail('CreateLink should find its parent k-html-editor');
|
|
82
|
+
}
|
|
83
|
+
cleanup(container);
|
|
84
|
+
pass('CreateLink finds parent editor');
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
'click should open a dialog': async ({pass, fail}) => {
|
|
88
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
89
|
+
await control.updateComplete;
|
|
90
|
+
editor.getSelectedText = () => '';
|
|
91
|
+
control.shadowRoot.querySelector('button').click();
|
|
92
|
+
await new Promise(r => setTimeout(r, 100));
|
|
93
|
+
const dialog = document.querySelector('k-dialog');
|
|
94
|
+
if(!dialog){
|
|
95
|
+
cleanup(container);
|
|
96
|
+
return fail('Click should open a k-dialog');
|
|
97
|
+
}
|
|
98
|
+
dialog.remove();
|
|
99
|
+
cleanup(container);
|
|
100
|
+
pass('Click opens a dialog');
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
Code Mode Visibility
|
|
105
|
+
*/
|
|
106
|
+
'should hide in code mode': async ({pass, fail}) => {
|
|
107
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
108
|
+
editor.setMode('code');
|
|
109
|
+
await new Promise(r => editor.addEventListener('mode-changed', r, { once: true }));
|
|
110
|
+
await control.updateComplete;
|
|
111
|
+
if(!control.hidden){
|
|
112
|
+
cleanup(container);
|
|
113
|
+
return fail('CreateLink should be hidden in code mode');
|
|
114
|
+
}
|
|
115
|
+
cleanup(container);
|
|
116
|
+
pass('CreateLink is hidden in code mode');
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
'should be visible in visual mode': async ({pass, fail}) => {
|
|
120
|
+
const { container, editor, control } = await createEditorWithControl();
|
|
121
|
+
await control.updateComplete;
|
|
122
|
+
if(control.hidden){
|
|
123
|
+
cleanup(container);
|
|
124
|
+
return fail('CreateLink should be visible in visual mode');
|
|
125
|
+
}
|
|
126
|
+
cleanup(container);
|
|
127
|
+
pass('CreateLink is visible in visual mode');
|
|
128
|
+
},
|
|
129
|
+
};
|