kempo-ui 0.3.9 → 0.3.11

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.
Files changed (25) hide show
  1. package/dist/components/HtmlEditor.js +15 -15
  2. package/docs/src/components/HtmlEditor.js +15 -15
  3. package/package.json +3 -3
  4. package/src/components/HtmlEditor.js +24 -29
  5. package/tests/components/htmlEditorControls/Align.browser-test.js +203 -0
  6. package/tests/components/htmlEditorControls/Bold.browser-test.js +127 -0
  7. package/tests/components/htmlEditorControls/BulletList.browser-test.js +127 -0
  8. package/tests/components/htmlEditorControls/CharacterCount.browser-test.js +106 -0
  9. package/tests/components/htmlEditorControls/ClearFormatting.browser-test.js +127 -0
  10. package/tests/components/htmlEditorControls/CodeBlock.browser-test.js +143 -0
  11. package/tests/components/htmlEditorControls/ControlGroup.browser-test.js +116 -0
  12. package/tests/components/htmlEditorControls/ControlSpacer.browser-test.js +69 -0
  13. package/tests/components/htmlEditorControls/CreateLink.browser-test.js +129 -0
  14. package/tests/components/htmlEditorControls/DropdownControl.browser-test.js +138 -0
  15. package/tests/components/htmlEditorControls/FormatBlock.browser-test.js +163 -0
  16. package/tests/components/htmlEditorControls/InlineCode.browser-test.js +127 -0
  17. package/tests/components/htmlEditorControls/InsertTable.browser-test.js +129 -0
  18. package/tests/components/htmlEditorControls/Italic.browser-test.js +127 -0
  19. package/tests/components/htmlEditorControls/Mode.browser-test.js +138 -0
  20. package/tests/components/htmlEditorControls/NumberList.browser-test.js +127 -0
  21. package/tests/components/htmlEditorControls/Strikethrough.browser-test.js +127 -0
  22. package/tests/components/htmlEditorControls/TextBackgroundColor.browser-test.js +136 -0
  23. package/tests/components/htmlEditorControls/TextColor.browser-test.js +136 -0
  24. package/tests/components/htmlEditorControls/Underline.browser-test.js +127 -0
  25. package/tests/components/htmlEditorControls/WordCount.browser-test.js +106 -0
@@ -0,0 +1,127 @@
1
+ import '../../../src/components/HtmlEditor.js';
2
+ import NumberList from '../../../src/components/htmlEditorControls/NumberList.js';
3
+
4
+ const createEditorWithControl = async () => {
5
+ const container = document.createElement('div');
6
+ container.innerHTML = `
7
+ <k-html-editor>
8
+ <k-hec-number-list slot="toolbar-top-left"></k-hec-number-list>
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-number-list');
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-number-list element': async ({pass, fail}) => {
27
+ const { container, control } = await createEditorWithControl();
28
+ if(!(control instanceof NumberList)){
29
+ cleanup(container);
30
+ return fail('Element should be instance of NumberList');
31
+ }
32
+ cleanup(container);
33
+ pass('NumberList 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('NumberList should have shadow root');
41
+ }
42
+ cleanup(container);
43
+ pass('NumberList 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('NumberList should render a button');
53
+ }
54
+ cleanup(container);
55
+ pass('NumberList renders a button');
56
+ },
57
+
58
+ 'should render format_list_numbered 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('NumberList should render a k-icon');
65
+ }
66
+ if(icon.getAttribute('name') !== 'format_list_numbered'){
67
+ cleanup(container);
68
+ return fail(`Expected icon name "format_list_numbered", got "${icon.getAttribute('name')}"`);
69
+ }
70
+ cleanup(container);
71
+ pass('NumberList renders format_list_numbered 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('NumberList should find its parent k-html-editor');
82
+ }
83
+ cleanup(container);
84
+ pass('NumberList finds parent editor');
85
+ },
86
+
87
+ 'click should call editor.orderedList()': async ({pass, fail}) => {
88
+ const { container, editor, control } = await createEditorWithControl();
89
+ await control.updateComplete;
90
+ let called = false;
91
+ editor.orderedList = () => { called = true; };
92
+ control.shadowRoot.querySelector('button').click();
93
+ if(!called){
94
+ cleanup(container);
95
+ return fail('Click should call editor.orderedList()');
96
+ }
97
+ cleanup(container);
98
+ pass('Click calls editor.orderedList()');
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('NumberList should be hidden in code mode');
112
+ }
113
+ cleanup(container);
114
+ pass('NumberList 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('NumberList should be visible in visual mode');
123
+ }
124
+ cleanup(container);
125
+ pass('NumberList is visible in visual mode');
126
+ },
127
+ };
@@ -0,0 +1,127 @@
1
+ import '../../../src/components/HtmlEditor.js';
2
+ import Strikethrough from '../../../src/components/htmlEditorControls/Strikethrough.js';
3
+
4
+ const createEditorWithControl = async () => {
5
+ const container = document.createElement('div');
6
+ container.innerHTML = `
7
+ <k-html-editor>
8
+ <k-hec-strikethrough slot="toolbar-top-left"></k-hec-strikethrough>
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-strikethrough');
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-strikethrough element': async ({pass, fail}) => {
27
+ const { container, control } = await createEditorWithControl();
28
+ if(!(control instanceof Strikethrough)){
29
+ cleanup(container);
30
+ return fail('Element should be instance of Strikethrough');
31
+ }
32
+ cleanup(container);
33
+ pass('Strikethrough 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('Strikethrough should have shadow root');
41
+ }
42
+ cleanup(container);
43
+ pass('Strikethrough 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('Strikethrough should render a button');
53
+ }
54
+ cleanup(container);
55
+ pass('Strikethrough renders a button');
56
+ },
57
+
58
+ 'should render strikethrough_s 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('Strikethrough should render a k-icon');
65
+ }
66
+ if(icon.getAttribute('name') !== 'strikethrough_s'){
67
+ cleanup(container);
68
+ return fail(`Expected icon name "strikethrough_s", got "${icon.getAttribute('name')}"`);
69
+ }
70
+ cleanup(container);
71
+ pass('Strikethrough renders strikethrough_s 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('Strikethrough should find its parent k-html-editor');
82
+ }
83
+ cleanup(container);
84
+ pass('Strikethrough finds parent editor');
85
+ },
86
+
87
+ 'click should call editor.strikethrough()': async ({pass, fail}) => {
88
+ const { container, editor, control } = await createEditorWithControl();
89
+ await control.updateComplete;
90
+ let called = false;
91
+ editor.strikethrough = () => { called = true; };
92
+ control.shadowRoot.querySelector('button').click();
93
+ if(!called){
94
+ cleanup(container);
95
+ return fail('Click should call editor.strikethrough()');
96
+ }
97
+ cleanup(container);
98
+ pass('Click calls editor.strikethrough()');
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('Strikethrough should be hidden in code mode');
112
+ }
113
+ cleanup(container);
114
+ pass('Strikethrough 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('Strikethrough should be visible in visual mode');
123
+ }
124
+ cleanup(container);
125
+ pass('Strikethrough is visible in visual mode');
126
+ },
127
+ };
@@ -0,0 +1,136 @@
1
+ import '../../../src/components/HtmlEditor.js';
2
+ import TextBackgroundColor from '../../../src/components/htmlEditorControls/TextBackgroundColor.js';
3
+
4
+ const createEditorWithControl = async () => {
5
+ const container = document.createElement('div');
6
+ container.innerHTML = `
7
+ <k-html-editor>
8
+ <k-hec-text-background-color slot="toolbar-top-left"></k-hec-text-background-color>
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-text-background-color');
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-text-bg-color element': async ({pass, fail}) => {
27
+ const { container, control } = await createEditorWithControl();
28
+ if(!(control instanceof TextBackgroundColor)){
29
+ cleanup(container);
30
+ return fail('Element should be instance of TextBackgroundColor');
31
+ }
32
+ cleanup(container);
33
+ pass('TextBackgroundColor 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('TextBackgroundColor should have shadow root');
41
+ }
42
+ cleanup(container);
43
+ pass('TextBackgroundColor has shadow root');
44
+ },
45
+
46
+ 'should have default colors': async ({pass, fail}) => {
47
+ const { container, control } = await createEditorWithControl();
48
+ if(!control.colors || control.colors.length === 0){
49
+ cleanup(container);
50
+ return fail('TextBackgroundColor should have default colors');
51
+ }
52
+ if(!control.colors.includes('#ffff00')){
53
+ cleanup(container);
54
+ return fail('TextBackgroundColor default colors should include #ffff00');
55
+ }
56
+ cleanup(container);
57
+ pass('TextBackgroundColor has default colors');
58
+ },
59
+
60
+ /*
61
+ Editor Integration
62
+ */
63
+ 'should find parent editor': async ({pass, fail}) => {
64
+ const { container, editor, control } = await createEditorWithControl();
65
+ if(control.editor !== editor){
66
+ cleanup(container);
67
+ return fail('TextBackgroundColor should find its parent k-html-editor');
68
+ }
69
+ cleanup(container);
70
+ pass('TextBackgroundColor finds parent editor');
71
+ },
72
+
73
+ 'handleRemove should call editor.removeTextBackgroundColor()': async ({pass, fail}) => {
74
+ const { container, editor, control } = await createEditorWithControl();
75
+ let called = false;
76
+ editor.removeTextBackgroundColor = () => { called = true; };
77
+ control.handleRemove();
78
+ if(!called){
79
+ cleanup(container);
80
+ return fail('handleRemove should call editor.removeTextBackgroundColor()');
81
+ }
82
+ cleanup(container);
83
+ pass('handleRemove calls editor.removeTextBackgroundColor()');
84
+ },
85
+
86
+ 'handleRemove should close dropdown': async ({pass, fail}) => {
87
+ const { container, control } = await createEditorWithControl();
88
+ control.opened = true;
89
+ control.handleRemove();
90
+ if(control.opened){
91
+ cleanup(container);
92
+ return fail('handleRemove should close the dropdown');
93
+ }
94
+ cleanup(container);
95
+ pass('handleRemove closes the dropdown');
96
+ },
97
+
98
+ /*
99
+ Properties
100
+ */
101
+ 'disableRemove should default to false': async ({pass, fail}) => {
102
+ const { container, control } = await createEditorWithControl();
103
+ if(control.disableRemove !== false){
104
+ cleanup(container);
105
+ return fail('disableRemove should default to false');
106
+ }
107
+ cleanup(container);
108
+ pass('disableRemove defaults to false');
109
+ },
110
+
111
+ 'disablePicker should default to false': async ({pass, fail}) => {
112
+ const { container, control } = await createEditorWithControl();
113
+ if(control.disablePicker !== false){
114
+ cleanup(container);
115
+ return fail('disablePicker should default to false');
116
+ }
117
+ cleanup(container);
118
+ pass('disablePicker defaults to false');
119
+ },
120
+
121
+ /*
122
+ Code Mode Visibility
123
+ */
124
+ 'should hide in code mode': async ({pass, fail}) => {
125
+ const { container, editor, control } = await createEditorWithControl();
126
+ editor.setMode('code');
127
+ await new Promise(r => editor.addEventListener('mode-changed', r, { once: true }));
128
+ await control.updateComplete;
129
+ if(!control.hidden){
130
+ cleanup(container);
131
+ return fail('TextBackgroundColor should be hidden in code mode');
132
+ }
133
+ cleanup(container);
134
+ pass('TextBackgroundColor is hidden in code mode');
135
+ },
136
+ };
@@ -0,0 +1,136 @@
1
+ import '../../../src/components/HtmlEditor.js';
2
+ import TextColor from '../../../src/components/htmlEditorControls/TextColor.js';
3
+
4
+ const createEditorWithControl = async () => {
5
+ const container = document.createElement('div');
6
+ container.innerHTML = `
7
+ <k-html-editor>
8
+ <k-hec-text-color slot="toolbar-top-left"></k-hec-text-color>
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-text-color');
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-text-color element': async ({pass, fail}) => {
27
+ const { container, control } = await createEditorWithControl();
28
+ if(!(control instanceof TextColor)){
29
+ cleanup(container);
30
+ return fail('Element should be instance of TextColor');
31
+ }
32
+ cleanup(container);
33
+ pass('TextColor 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('TextColor should have shadow root');
41
+ }
42
+ cleanup(container);
43
+ pass('TextColor has shadow root');
44
+ },
45
+
46
+ 'should have default colors': async ({pass, fail}) => {
47
+ const { container, control } = await createEditorWithControl();
48
+ if(!control.colors || control.colors.length === 0){
49
+ cleanup(container);
50
+ return fail('TextColor should have default colors');
51
+ }
52
+ if(!control.colors.includes('#000000')){
53
+ cleanup(container);
54
+ return fail('TextColor default colors should include #000000');
55
+ }
56
+ cleanup(container);
57
+ pass('TextColor has default colors');
58
+ },
59
+
60
+ /*
61
+ Editor Integration
62
+ */
63
+ 'should find parent editor': async ({pass, fail}) => {
64
+ const { container, editor, control } = await createEditorWithControl();
65
+ if(control.editor !== editor){
66
+ cleanup(container);
67
+ return fail('TextColor should find its parent k-html-editor');
68
+ }
69
+ cleanup(container);
70
+ pass('TextColor finds parent editor');
71
+ },
72
+
73
+ 'handleRemove should call editor.removeTextColor()': async ({pass, fail}) => {
74
+ const { container, editor, control } = await createEditorWithControl();
75
+ let called = false;
76
+ editor.removeTextColor = () => { called = true; };
77
+ control.handleRemove();
78
+ if(!called){
79
+ cleanup(container);
80
+ return fail('handleRemove should call editor.removeTextColor()');
81
+ }
82
+ cleanup(container);
83
+ pass('handleRemove calls editor.removeTextColor()');
84
+ },
85
+
86
+ 'handleRemove should close dropdown': async ({pass, fail}) => {
87
+ const { container, control } = await createEditorWithControl();
88
+ control.opened = true;
89
+ control.handleRemove();
90
+ if(control.opened){
91
+ cleanup(container);
92
+ return fail('handleRemove should close the dropdown');
93
+ }
94
+ cleanup(container);
95
+ pass('handleRemove closes the dropdown');
96
+ },
97
+
98
+ /*
99
+ Properties
100
+ */
101
+ 'disableRemove should default to false': async ({pass, fail}) => {
102
+ const { container, control } = await createEditorWithControl();
103
+ if(control.disableRemove !== false){
104
+ cleanup(container);
105
+ return fail('disableRemove should default to false');
106
+ }
107
+ cleanup(container);
108
+ pass('disableRemove defaults to false');
109
+ },
110
+
111
+ 'disablePicker should default to false': async ({pass, fail}) => {
112
+ const { container, control } = await createEditorWithControl();
113
+ if(control.disablePicker !== false){
114
+ cleanup(container);
115
+ return fail('disablePicker should default to false');
116
+ }
117
+ cleanup(container);
118
+ pass('disablePicker defaults to false');
119
+ },
120
+
121
+ /*
122
+ Code Mode Visibility
123
+ */
124
+ 'should hide in code mode': async ({pass, fail}) => {
125
+ const { container, editor, control } = await createEditorWithControl();
126
+ editor.setMode('code');
127
+ await new Promise(r => editor.addEventListener('mode-changed', r, { once: true }));
128
+ await control.updateComplete;
129
+ if(!control.hidden){
130
+ cleanup(container);
131
+ return fail('TextColor should be hidden in code mode');
132
+ }
133
+ cleanup(container);
134
+ pass('TextColor is hidden in code mode');
135
+ },
136
+ };
@@ -0,0 +1,127 @@
1
+ import '../../../src/components/HtmlEditor.js';
2
+ import Underline from '../../../src/components/htmlEditorControls/Underline.js';
3
+
4
+ const createEditorWithControl = async () => {
5
+ const container = document.createElement('div');
6
+ container.innerHTML = `
7
+ <k-html-editor>
8
+ <k-hec-underline slot="toolbar-top-left"></k-hec-underline>
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-underline');
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-underline element': async ({pass, fail}) => {
27
+ const { container, control } = await createEditorWithControl();
28
+ if(!(control instanceof Underline)){
29
+ cleanup(container);
30
+ return fail('Element should be instance of Underline');
31
+ }
32
+ cleanup(container);
33
+ pass('Underline 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('Underline should have shadow root');
41
+ }
42
+ cleanup(container);
43
+ pass('Underline 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('Underline should render a button');
53
+ }
54
+ cleanup(container);
55
+ pass('Underline renders a button');
56
+ },
57
+
58
+ 'should render format_underlined 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('Underline should render a k-icon');
65
+ }
66
+ if(icon.getAttribute('name') !== 'format_underlined'){
67
+ cleanup(container);
68
+ return fail(`Expected icon name "format_underlined", got "${icon.getAttribute('name')}"`);
69
+ }
70
+ cleanup(container);
71
+ pass('Underline renders format_underlined 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('Underline should find its parent k-html-editor');
82
+ }
83
+ cleanup(container);
84
+ pass('Underline finds parent editor');
85
+ },
86
+
87
+ 'click should call editor.underline()': async ({pass, fail}) => {
88
+ const { container, editor, control } = await createEditorWithControl();
89
+ await control.updateComplete;
90
+ let called = false;
91
+ editor.underline = () => { called = true; };
92
+ control.shadowRoot.querySelector('button').click();
93
+ if(!called){
94
+ cleanup(container);
95
+ return fail('Click should call editor.underline()');
96
+ }
97
+ cleanup(container);
98
+ pass('Click calls editor.underline()');
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('Underline should be hidden in code mode');
112
+ }
113
+ cleanup(container);
114
+ pass('Underline 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('Underline should be visible in visual mode');
123
+ }
124
+ cleanup(container);
125
+ pass('Underline is visible in visual mode');
126
+ },
127
+ };