Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp

Issue 2493703002: Make "compositionend" event fired after setting caret position (Closed)
Patch Set: format Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/editing/InputMethodController.h" 5 #include "core/editing/InputMethodController.h"
6 6
7 #include "core/dom/Document.h" 7 #include "core/dom/Document.h"
8 #include "core/dom/Element.h" 8 #include "core/dom/Element.h"
9 #include "core/dom/Range.h" 9 #include "core/dom/Range.h"
10 #include "core/editing/Editor.h" 10 #include "core/editing/Editor.h"
(...skipping 10 matching lines...) Expand all
21 namespace blink { 21 namespace blink {
22 22
23 class InputMethodControllerTest : public ::testing::Test { 23 class InputMethodControllerTest : public ::testing::Test {
24 protected: 24 protected:
25 InputMethodController& controller() { 25 InputMethodController& controller() {
26 return frame().inputMethodController(); 26 return frame().inputMethodController();
27 } 27 }
28 Document& document() const { return *m_document; } 28 Document& document() const { return *m_document; }
29 LocalFrame& frame() const { return m_dummyPageHolder->frame(); } 29 LocalFrame& frame() const { return m_dummyPageHolder->frame(); }
30 Element* insertHTMLElement(const char* elementCode, const char* elementId); 30 Element* insertHTMLElement(const char* elementCode, const char* elementId);
31 void createHTMLWithCompositionInputEventListeners();
32 void createHTMLWithCompositionEndEventListener(const SelectionType);
31 33
32 private: 34 private:
33 void SetUp() override; 35 void SetUp() override;
34 36
35 std::unique_ptr<DummyPageHolder> m_dummyPageHolder; 37 std::unique_ptr<DummyPageHolder> m_dummyPageHolder;
36 Persistent<Document> m_document; 38 Persistent<Document> m_document;
37 }; 39 };
38 40
39 void InputMethodControllerTest::SetUp() { 41 void InputMethodControllerTest::SetUp() {
40 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); 42 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600));
41 m_document = &m_dummyPageHolder->document(); 43 m_document = &m_dummyPageHolder->document();
42 DCHECK(m_document); 44 DCHECK(m_document);
43 } 45 }
44 46
45 Element* InputMethodControllerTest::insertHTMLElement(const char* elementCode, 47 Element* InputMethodControllerTest::insertHTMLElement(const char* elementCode,
46 const char* elementId) { 48 const char* elementId) {
47 document().write(elementCode); 49 document().write(elementCode);
48 document().updateStyleAndLayout(); 50 document().updateStyleAndLayout();
49 Element* element = document().getElementById(elementId); 51 Element* element = document().getElementById(elementId);
50 element->focus(); 52 element->focus();
51 return element; 53 return element;
52 } 54 }
53 55
56 void InputMethodControllerTest::createHTMLWithCompositionInputEventListeners() {
57 document().settings()->setScriptEnabled(true);
58 Element* editable =
59 insertHTMLElement("<div id='sample' contenteditable></div>", "sample");
60 Element* script = document().createElement("script");
61 script->setInnerHTML(
62 "document.getElementById('sample').addEventListener('beforeinput', "
63 " event => document.title = `beforeinput.data:${event.data};`);"
64 "document.getElementById('sample').addEventListener('input', "
65 " event => document.title += `input.data:${event.data};`);"
66 "document.getElementById('sample').addEventListener('compositionend', "
67 " event => document.title += `compositionend.data:${event.data};`);");
68 document().body()->appendChild(script);
69 document().view()->updateAllLifecyclePhases();
70 editable->focus();
71 }
72
73 void InputMethodControllerTest::createHTMLWithCompositionEndEventListener(
74 const SelectionType type) {
75 document().settings()->setScriptEnabled(true);
76 Element* editable =
77 insertHTMLElement("<div id='sample' contentEditable></div>", "sample");
78 Element* script = document().createElement("script");
79
80 switch (type) {
81 case NoSelection:
82 script->setInnerHTML(
83 // If the caret position is set before firing 'compositonend' event
84 // (and it should), the final caret position will be reset to null.
85 "document.getElementById('sample').addEventListener('compositionend',"
86 " event => getSelection().removeAllRanges());");
87 break;
88 case CaretSelection:
89 script->setInnerHTML(
90 // If the caret position is set before firing 'compositonend' event
91 // (and it should), the final caret position will be reset to [3,3].
92 "document.getElementById('sample').addEventListener('compositionend',"
93 " event => {"
94 " const node = document.getElementById('sample').firstChild;"
95 " getSelection().collapse(node, 3);"
96 "});");
97 break;
98 case RangeSelection:
99 script->setInnerHTML(
100 // If the caret position is set before firing 'compositonend' event
101 // (and it should), the final caret position will be reset to [2,4].
102 "document.getElementById('sample').addEventListener('compositionend',"
103 " event => {"
104 " const node = document.getElementById('sample').firstChild;"
105 " const selection = getSelection();"
106 " selection.collapse(node, 2);"
107 " selection.extend(node, 4);"
108 "});");
109 break;
110 default:
111 NOTREACHED();
112 }
113 document().body()->appendChild(script);
114 document().view()->updateAllLifecyclePhases();
115 editable->focus();
116 }
117
54 TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput) { 118 TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput) {
55 HTMLInputElement* input = 119 HTMLInputElement* input =
56 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); 120 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample"));
57 121
58 input->setValue("fooX"); 122 input->setValue("fooX");
59 document().updateStyleAndLayout(); 123 document().updateStyleAndLayout();
60 controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); 124 controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
61 EXPECT_STREQ("fooX", input->value().utf8().data()); 125 EXPECT_STREQ("fooX", input->value().utf8().data());
62 controller().extendSelectionAndDelete(0, 0); 126 controller().extendSelectionAndDelete(0, 0);
63 EXPECT_STREQ("fooX", input->value().utf8().data()); 127 EXPECT_STREQ("fooX", input->value().utf8().data());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 input->setValue("fooX"); 160 input->setValue("fooX");
97 document().updateStyleAndLayout(); 161 document().updateStyleAndLayout();
98 controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); 162 controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
99 EXPECT_STREQ("fooX", input->value().utf8().data()); 163 EXPECT_STREQ("fooX", input->value().utf8().data());
100 controller().extendSelectionAndDelete(0, 1); 164 controller().extendSelectionAndDelete(0, 1);
101 EXPECT_STREQ("fooX", input->value().utf8().data()); 165 EXPECT_STREQ("fooX", input->value().utf8().data());
102 } 166 }
103 167
104 TEST_F(InputMethodControllerTest, SetCompositionFromExistingText) { 168 TEST_F(InputMethodControllerTest, SetCompositionFromExistingText) {
105 Element* div = insertHTMLElement( 169 Element* div = insertHTMLElement(
106 "<div id='sample' contenteditable='true'>hello world</div>", "sample"); 170 "<div id='sample' contenteditable>hello world</div>", "sample");
107 171
108 Vector<CompositionUnderline> underlines; 172 Vector<CompositionUnderline> underlines;
109 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 173 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
110 controller().setCompositionFromExistingText(underlines, 0, 5); 174 controller().setCompositionFromExistingText(underlines, 0, 5);
111 175
112 Range* range = controller().compositionRange(); 176 Range* range = controller().compositionRange();
113 EXPECT_EQ(0, range->startOffset()); 177 EXPECT_EQ(0, range->startOffset());
114 EXPECT_EQ(5, range->endOffset()); 178 EXPECT_EQ(5, range->endOffset());
115 179
116 PlainTextRange plainTextRange(PlainTextRange::create(*div, *range)); 180 PlainTextRange plainTextRange(PlainTextRange::create(*div, *range));
117 EXPECT_EQ(0u, plainTextRange.start()); 181 EXPECT_EQ(0u, plainTextRange.start());
118 EXPECT_EQ(5u, plainTextRange.end()); 182 EXPECT_EQ(5u, plainTextRange.end());
119 } 183 }
120 184
121 TEST_F(InputMethodControllerTest, SetCompositionKeepingStyle) { 185 TEST_F(InputMethodControllerTest, SetCompositionKeepingStyle) {
122 Element* div = insertHTMLElement( 186 Element* div = insertHTMLElement(
123 "<div id='sample' " 187 "<div id='sample' "
124 "contenteditable='true'>abc1<b>2</b>34567<b>8</b>9</div>", 188 "contenteditable>abc1<b>2</b>34567<b>8</b>9</div>",
125 "sample"); 189 "sample");
126 190
127 Vector<CompositionUnderline> underlines; 191 Vector<CompositionUnderline> underlines;
128 underlines.append(CompositionUnderline(3, 12, Color(255, 0, 0), false, 0)); 192 underlines.append(CompositionUnderline(3, 12, Color(255, 0, 0), false, 0));
129 controller().setCompositionFromExistingText(underlines, 3, 12); 193 controller().setCompositionFromExistingText(underlines, 3, 12);
130 194
131 // Subtract a character. 195 // Subtract a character.
132 controller().setComposition(String("12345789"), underlines, 8, 8); 196 controller().setComposition(String("12345789"), underlines, 8, 8);
133 EXPECT_STREQ("abc1<b>2</b>3457<b>8</b>9", div->innerHTML().utf8().data()); 197 EXPECT_STREQ("abc1<b>2</b>3457<b>8</b>9", div->innerHTML().utf8().data());
134 198
135 // Append a character. 199 // Append a character.
136 controller().setComposition(String("123456789"), underlines, 9, 9); 200 controller().setComposition(String("123456789"), underlines, 9, 9);
137 EXPECT_STREQ("abc1<b>2</b>34567<b>8</b>9", div->innerHTML().utf8().data()); 201 EXPECT_STREQ("abc1<b>2</b>34567<b>8</b>9", div->innerHTML().utf8().data());
138 202
139 // Subtract and append characters. 203 // Subtract and append characters.
140 controller().setComposition(String("123hello789"), underlines, 11, 11); 204 controller().setComposition(String("123hello789"), underlines, 11, 11);
141 EXPECT_STREQ("abc1<b>2</b>3hello7<b>8</b>9", div->innerHTML().utf8().data()); 205 EXPECT_STREQ("abc1<b>2</b>3hello7<b>8</b>9", div->innerHTML().utf8().data());
142 } 206 }
143 207
144 TEST_F(InputMethodControllerTest, SetCompositionWithEmojiKeepingStyle) { 208 TEST_F(InputMethodControllerTest, SetCompositionWithEmojiKeepingStyle) {
145 // U+1F3E0 = 0xF0 0x9F 0x8F 0xA0 (UTF8). It's an emoji character. 209 // U+1F3E0 = 0xF0 0x9F 0x8F 0xA0 (UTF8). It's an emoji character.
146 Element* div = insertHTMLElement( 210 Element* div = insertHTMLElement(
147 "<div id='sample' contenteditable='true'><b>&#x1f3e0</b></div>", 211 "<div id='sample' contenteditable><b>&#x1f3e0</b></div>", "sample");
148 "sample");
149 212
150 Vector<CompositionUnderline> underlines; 213 Vector<CompositionUnderline> underlines;
151 underlines.append(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); 214 underlines.append(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0));
152 215
153 controller().setCompositionFromExistingText(underlines, 0, 2); 216 controller().setCompositionFromExistingText(underlines, 0, 2);
154 217
155 // 0xF0 0x9F 0x8F 0xAB is also an emoji character, with the same leading 218 // 0xF0 0x9F 0x8F 0xAB is also an emoji character, with the same leading
156 // surrogate pair to the previous one. 219 // surrogate pair to the previous one.
157 controller().setComposition(String::fromUTF8("\xF0\x9F\x8F\xAB"), underlines, 220 controller().setComposition(String::fromUTF8("\xF0\x9F\x8F\xAB"), underlines,
158 2, 2); 221 2, 2);
159 EXPECT_STREQ("<b>\xF0\x9F\x8F\xAB</b>", div->innerHTML().utf8().data()); 222 EXPECT_STREQ("<b>\xF0\x9F\x8F\xAB</b>", div->innerHTML().utf8().data());
160 223
161 controller().setComposition(String::fromUTF8("\xF0\x9F\x8F\xA0"), underlines, 224 controller().setComposition(String::fromUTF8("\xF0\x9F\x8F\xA0"), underlines,
162 2, 2); 225 2, 2);
163 EXPECT_STREQ("<b>\xF0\x9F\x8F\xA0</b>", div->innerHTML().utf8().data()); 226 EXPECT_STREQ("<b>\xF0\x9F\x8F\xA0</b>", div->innerHTML().utf8().data());
164 } 227 }
165 228
166 TEST_F(InputMethodControllerTest, 229 TEST_F(InputMethodControllerTest,
167 SetCompositionWithTeluguSignVisargaKeepingStyle) { 230 SetCompositionWithTeluguSignVisargaKeepingStyle) {
168 // U+0C03 = 0xE0 0xB0 0x83 (UTF8), a telugu sign visarga with one code point. 231 // U+0C03 = 0xE0 0xB0 0x83 (UTF8), a telugu sign visarga with one code point.
169 // It's one grapheme cluster if separated. It can also form one grapheme 232 // It's one grapheme cluster if separated. It can also form one grapheme
170 // cluster with another code point(e.g, itself). 233 // cluster with another code point(e.g, itself).
171 Element* div = insertHTMLElement( 234 Element* div = insertHTMLElement(
172 "<div id='sample' contenteditable='true'><b>&#xc03</b></div>", "sample"); 235 "<div id='sample' contenteditable><b>&#xc03</b></div>", "sample");
173 236
174 Vector<CompositionUnderline> underlines; 237 Vector<CompositionUnderline> underlines;
175 underlines.append(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); 238 underlines.append(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0));
176 controller().setCompositionFromExistingText(underlines, 0, 1); 239 controller().setCompositionFromExistingText(underlines, 0, 1);
177 240
178 // 0xE0 0xB0 0x83 0xE0 0xB0 0x83, a telugu character with 2 code points in 241 // 0xE0 0xB0 0x83 0xE0 0xB0 0x83, a telugu character with 2 code points in
179 // 1 grapheme cluster. 242 // 1 grapheme cluster.
180 controller().setComposition(String::fromUTF8("\xE0\xB0\x83\xE0\xB0\x83"), 243 controller().setComposition(String::fromUTF8("\xE0\xB0\x83\xE0\xB0\x83"),
181 underlines, 2, 2); 244 underlines, 2, 2);
182 EXPECT_STREQ("<b>\xE0\xB0\x83\xE0\xB0\x83</b>", 245 EXPECT_STREQ("<b>\xE0\xB0\x83\xE0\xB0\x83</b>",
183 div->innerHTML().utf8().data()); 246 div->innerHTML().utf8().data());
184 247
185 controller().setComposition(String::fromUTF8("\xE0\xB0\x83"), underlines, 1, 248 controller().setComposition(String::fromUTF8("\xE0\xB0\x83"), underlines, 1,
186 1); 249 1);
187 EXPECT_STREQ("<b>\xE0\xB0\x83</b>", div->innerHTML().utf8().data()); 250 EXPECT_STREQ("<b>\xE0\xB0\x83</b>", div->innerHTML().utf8().data());
188 } 251 }
189 252
190 TEST_F(InputMethodControllerTest, SelectionOnConfirmExistingText) { 253 TEST_F(InputMethodControllerTest, SelectionOnConfirmExistingText) {
191 insertHTMLElement("<div id='sample' contenteditable='true'>hello world</div>", 254 insertHTMLElement("<div id='sample' contenteditable>hello world</div>",
192 "sample"); 255 "sample");
193 256
194 Vector<CompositionUnderline> underlines; 257 Vector<CompositionUnderline> underlines;
195 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 258 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
196 controller().setCompositionFromExistingText(underlines, 0, 5); 259 controller().setCompositionFromExistingText(underlines, 0, 5);
197 260
198 controller().finishComposingText(InputMethodController::KeepSelection); 261 controller().finishComposingText(InputMethodController::KeepSelection);
199 EXPECT_EQ(0, frame().selection().start().computeOffsetInContainerNode()); 262 EXPECT_EQ(0, frame().selection().start().computeOffsetInContainerNode());
200 EXPECT_EQ(0, frame().selection().end().computeOffsetInContainerNode()); 263 EXPECT_EQ(0, frame().selection().end().computeOffsetInContainerNode());
201 } 264 }
(...skipping 23 matching lines...) Expand all
225 controller().setComposition(String(""), underlines, 0, 3); 288 controller().setComposition(String(""), underlines, 0, 3);
226 289
227 EXPECT_STREQ("", input->value().utf8().data()); 290 EXPECT_STREQ("", input->value().utf8().data());
228 } 291 }
229 292
230 TEST_F(InputMethodControllerTest, 293 TEST_F(InputMethodControllerTest,
231 SetCompositionFromExistingTextWithCollapsedWhiteSpace) { 294 SetCompositionFromExistingTextWithCollapsedWhiteSpace) {
232 // Creates a div with one leading new line char. The new line char is hidden 295 // Creates a div with one leading new line char. The new line char is hidden
233 // from the user and IME, but is visible to InputMethodController. 296 // from the user and IME, but is visible to InputMethodController.
234 Element* div = insertHTMLElement( 297 Element* div = insertHTMLElement(
235 "<div id='sample' contenteditable='true'>\nhello world</div>", "sample"); 298 "<div id='sample' contenteditable>\nhello world</div>", "sample");
236 299
237 Vector<CompositionUnderline> underlines; 300 Vector<CompositionUnderline> underlines;
238 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 301 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
239 controller().setCompositionFromExistingText(underlines, 0, 5); 302 controller().setCompositionFromExistingText(underlines, 0, 5);
240 303
241 Range* range = controller().compositionRange(); 304 Range* range = controller().compositionRange();
242 EXPECT_EQ(1, range->startOffset()); 305 EXPECT_EQ(1, range->startOffset());
243 EXPECT_EQ(6, range->endOffset()); 306 EXPECT_EQ(6, range->endOffset());
244 307
245 PlainTextRange plainTextRange(PlainTextRange::create(*div, *range)); 308 PlainTextRange plainTextRange(PlainTextRange::create(*div, *range));
246 EXPECT_EQ(0u, plainTextRange.start()); 309 EXPECT_EQ(0u, plainTextRange.start());
247 EXPECT_EQ(5u, plainTextRange.end()); 310 EXPECT_EQ(5u, plainTextRange.end());
248 } 311 }
249 312
250 TEST_F(InputMethodControllerTest, 313 TEST_F(InputMethodControllerTest,
251 SetCompositionFromExistingTextWithInvalidOffsets) { 314 SetCompositionFromExistingTextWithInvalidOffsets) {
252 insertHTMLElement("<div id='sample' contenteditable='true'>test</div>", 315 insertHTMLElement("<div id='sample' contenteditable>test</div>", "sample");
253 "sample");
254 316
255 Vector<CompositionUnderline> underlines; 317 Vector<CompositionUnderline> underlines;
256 underlines.append(CompositionUnderline(7, 8, Color(255, 0, 0), false, 0)); 318 underlines.append(CompositionUnderline(7, 8, Color(255, 0, 0), false, 0));
257 controller().setCompositionFromExistingText(underlines, 7, 8); 319 controller().setCompositionFromExistingText(underlines, 7, 8);
258 320
259 EXPECT_FALSE(controller().compositionRange()); 321 EXPECT_FALSE(controller().compositionRange());
260 } 322 }
261 323
262 TEST_F(InputMethodControllerTest, ConfirmPasswordComposition) { 324 TEST_F(InputMethodControllerTest, ConfirmPasswordComposition) {
263 HTMLInputElement* input = toHTMLInputElement(insertHTMLElement( 325 HTMLInputElement* input = toHTMLInputElement(insertHTMLElement(
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 document().updateStyleAndLayout(); 612 document().updateStyleAndLayout();
551 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); 613 controller().setEditableSelectionOffsets(PlainTextRange(2, 2));
552 EXPECT_STREQ("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86", 614 EXPECT_STREQ("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86",
553 input->value().utf8().data()); 615 input->value().utf8().data());
554 controller().deleteSurroundingText(1, 1); 616 controller().deleteSurroundingText(1, 1);
555 EXPECT_STREQ("", input->value().utf8().data()); 617 EXPECT_STREQ("", input->value().utf8().data());
556 } 618 }
557 619
558 TEST_F(InputMethodControllerTest, DeleteSurroundingTextForMultipleNodes) { 620 TEST_F(InputMethodControllerTest, DeleteSurroundingTextForMultipleNodes) {
559 Element* div = insertHTMLElement( 621 Element* div = insertHTMLElement(
560 "<div id='sample' contenteditable='true'>aaa" 622 "<div id='sample' contenteditable>aaa"
561 "<div id='sample2' contenteditable='true'>bbb" 623 "<div id='sample2' contenteditable>bbb"
562 "<div id='sample3' contenteditable='true'>ccc" 624 "<div id='sample3' contenteditable>ccc"
563 "<div id='sample4' contenteditable='true'>ddd" 625 "<div id='sample4' contenteditable>ddd"
564 "<div id='sample5' contenteditable='true'>eee" 626 "<div id='sample5' contenteditable>eee"
565 "</div></div></div></div></div>", 627 "</div></div></div></div></div>",
566 "sample"); 628 "sample");
567 629
568 controller().setEditableSelectionOffsets(PlainTextRange(8, 8)); 630 controller().setEditableSelectionOffsets(PlainTextRange(8, 8));
569 EXPECT_STREQ("aaa\nbbb\nccc\nddd\neee", div->innerText().utf8().data()); 631 EXPECT_STREQ("aaa\nbbb\nccc\nddd\neee", div->innerText().utf8().data());
570 EXPECT_EQ(8u, controller().getSelectionOffsets().start()); 632 EXPECT_EQ(8u, controller().getSelectionOffsets().start());
571 EXPECT_EQ(8u, controller().getSelectionOffsets().end()); 633 EXPECT_EQ(8u, controller().getSelectionOffsets().end());
572 634
573 controller().deleteSurroundingText(1, 0); 635 controller().deleteSurroundingText(1, 0);
574 EXPECT_STREQ("aaa\nbbbccc\nddd\neee", div->innerText().utf8().data()); 636 EXPECT_STREQ("aaa\nbbbccc\nddd\neee", div->innerText().utf8().data());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 EXPECT_STREQ("heABllo", input->value().utf8().data()); 703 EXPECT_STREQ("heABllo", input->value().utf8().data());
642 EXPECT_EQ(7u, controller().getSelectionOffsets().start()); 704 EXPECT_EQ(7u, controller().getSelectionOffsets().start());
643 EXPECT_EQ(7u, controller().getSelectionOffsets().end()); 705 EXPECT_EQ(7u, controller().getSelectionOffsets().end());
644 } 706 }
645 707
646 TEST_F(InputMethodControllerTest, 708 TEST_F(InputMethodControllerTest,
647 SetCompositionForContentEditableWithNewCaretPositions) { 709 SetCompositionForContentEditableWithNewCaretPositions) {
648 // There are 7 nodes and 5+1+5+1+3+4+3 characters: "hello", '\n', "world", 710 // There are 7 nodes and 5+1+5+1+3+4+3 characters: "hello", '\n', "world",
649 // "\n", "012", "3456", "789". 711 // "\n", "012", "3456", "789".
650 Element* div = insertHTMLElement( 712 Element* div = insertHTMLElement(
651 "<div id='sample' contenteditable='true'>" 713 "<div id='sample' contenteditable>"
652 "hello" 714 "hello"
653 "<div id='sample2' contenteditable='true'>world" 715 "<div id='sample2' contenteditable>world"
654 "<p>012<b>3456</b><i>789</i></p>" 716 "<p>012<b>3456</b><i>789</i></p>"
655 "</div>" 717 "</div>"
656 "</div>", 718 "</div>",
657 "sample"); 719 "sample");
658 720
659 controller().setEditableSelectionOffsets(PlainTextRange(17, 17)); 721 controller().setEditableSelectionOffsets(PlainTextRange(17, 17));
660 EXPECT_STREQ("hello\nworld\n0123456789", div->innerText().utf8().data()); 722 EXPECT_STREQ("hello\nworld\n0123456789", div->innerText().utf8().data());
661 EXPECT_EQ(17u, controller().getSelectionOffsets().start()); 723 EXPECT_EQ(17u, controller().getSelectionOffsets().start());
662 EXPECT_EQ(17u, controller().getSelectionOffsets().end()); 724 EXPECT_EQ(17u, controller().getSelectionOffsets().end());
663 725
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 // The caret exceeds right boundary. 799 // The caret exceeds right boundary.
738 // "hello\nworld\n01234AB56789*". 800 // "hello\nworld\n01234AB56789*".
739 controller().setComposition("AB", underlines, 100, 100); 801 controller().setComposition("AB", underlines, 100, 100);
740 EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().utf8().data()); 802 EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().utf8().data());
741 EXPECT_EQ(24u, controller().getSelectionOffsets().start()); 803 EXPECT_EQ(24u, controller().getSelectionOffsets().start());
742 EXPECT_EQ(24u, controller().getSelectionOffsets().end()); 804 EXPECT_EQ(24u, controller().getSelectionOffsets().end());
743 } 805 }
744 806
745 TEST_F(InputMethodControllerTest, SetCompositionWithEmptyText) { 807 TEST_F(InputMethodControllerTest, SetCompositionWithEmptyText) {
746 Element* div = insertHTMLElement( 808 Element* div = insertHTMLElement(
747 "<div id='sample' contenteditable='true'>hello</div>", "sample"); 809 "<div id='sample' contenteditable>hello</div>", "sample");
748 810
749 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); 811 controller().setEditableSelectionOffsets(PlainTextRange(2, 2));
750 EXPECT_STREQ("hello", div->innerText().utf8().data()); 812 EXPECT_STREQ("hello", div->innerText().utf8().data());
751 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); 813 EXPECT_EQ(2u, controller().getSelectionOffsets().start());
752 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); 814 EXPECT_EQ(2u, controller().getSelectionOffsets().end());
753 815
754 Vector<CompositionUnderline> underlines0; 816 Vector<CompositionUnderline> underlines0;
755 underlines0.append(CompositionUnderline(0, 0, Color(255, 0, 0), false, 0)); 817 underlines0.append(CompositionUnderline(0, 0, Color(255, 0, 0), false, 0));
756 Vector<CompositionUnderline> underlines2; 818 Vector<CompositionUnderline> underlines2;
757 underlines2.append(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); 819 underlines2.append(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0));
758 820
759 controller().setComposition("AB", underlines2, 2, 2); 821 controller().setComposition("AB", underlines2, 2, 2);
760 // With previous composition. 822 // With previous composition.
761 controller().setComposition("", underlines0, 2, 2); 823 controller().setComposition("", underlines0, 2, 2);
762 EXPECT_STREQ("hello", div->innerText().utf8().data()); 824 EXPECT_STREQ("hello", div->innerText().utf8().data());
763 EXPECT_EQ(4u, controller().getSelectionOffsets().start()); 825 EXPECT_EQ(4u, controller().getSelectionOffsets().start());
764 EXPECT_EQ(4u, controller().getSelectionOffsets().end()); 826 EXPECT_EQ(4u, controller().getSelectionOffsets().end());
765 827
766 // Without previous composition. 828 // Without previous composition.
767 controller().setComposition("", underlines0, -1, -1); 829 controller().setComposition("", underlines0, -1, -1);
768 EXPECT_STREQ("hello", div->innerText().utf8().data()); 830 EXPECT_STREQ("hello", div->innerText().utf8().data());
769 EXPECT_EQ(3u, controller().getSelectionOffsets().start()); 831 EXPECT_EQ(3u, controller().getSelectionOffsets().start());
770 EXPECT_EQ(3u, controller().getSelectionOffsets().end()); 832 EXPECT_EQ(3u, controller().getSelectionOffsets().end());
771 } 833 }
772 834
773 TEST_F(InputMethodControllerTest, InsertLineBreakWhileComposingText) { 835 TEST_F(InputMethodControllerTest, InsertLineBreakWhileComposingText) {
774 Element* div = insertHTMLElement( 836 Element* div =
775 "<div id='sample' contenteditable='true'></div>", "sample"); 837 insertHTMLElement("<div id='sample' contenteditable></div>", "sample");
776 838
777 Vector<CompositionUnderline> underlines; 839 Vector<CompositionUnderline> underlines;
778 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 840 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
779 controller().setComposition("hello", underlines, 5, 5); 841 controller().setComposition("hello", underlines, 5, 5);
780 EXPECT_STREQ("hello", div->innerText().utf8().data()); 842 EXPECT_STREQ("hello", div->innerText().utf8().data());
781 EXPECT_EQ(5u, controller().getSelectionOffsets().start()); 843 EXPECT_EQ(5u, controller().getSelectionOffsets().start());
782 EXPECT_EQ(5u, controller().getSelectionOffsets().end()); 844 EXPECT_EQ(5u, controller().getSelectionOffsets().end());
783 845
784 frame().editor().insertLineBreak(); 846 frame().editor().insertLineBreak();
785 EXPECT_STREQ("\n\n", div->innerText().utf8().data()); 847 EXPECT_STREQ("\n\n", div->innerText().utf8().data());
786 EXPECT_EQ(1u, controller().getSelectionOffsets().start()); 848 EXPECT_EQ(1u, controller().getSelectionOffsets().start());
787 EXPECT_EQ(1u, controller().getSelectionOffsets().end()); 849 EXPECT_EQ(1u, controller().getSelectionOffsets().end());
788 } 850 }
789 851
790 TEST_F(InputMethodControllerTest, InsertLineBreakAfterConfirmingText) { 852 TEST_F(InputMethodControllerTest, InsertLineBreakAfterConfirmingText) {
791 Element* div = insertHTMLElement( 853 Element* div =
792 "<div id='sample' contenteditable='true'></div>", "sample"); 854 insertHTMLElement("<div id='sample' contenteditable></div>", "sample");
793 855
794 controller().commitText("hello", 0); 856 controller().commitText("hello", 0);
795 EXPECT_STREQ("hello", div->innerText().utf8().data()); 857 EXPECT_STREQ("hello", div->innerText().utf8().data());
796 858
797 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); 859 controller().setEditableSelectionOffsets(PlainTextRange(2, 2));
798 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); 860 EXPECT_EQ(2u, controller().getSelectionOffsets().start());
799 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); 861 EXPECT_EQ(2u, controller().getSelectionOffsets().end());
800 862
801 frame().editor().insertLineBreak(); 863 frame().editor().insertLineBreak();
802 EXPECT_STREQ("he\nllo", div->innerText().utf8().data()); 864 EXPECT_STREQ("he\nllo", div->innerText().utf8().data());
803 EXPECT_EQ(3u, controller().getSelectionOffsets().start()); 865 EXPECT_EQ(3u, controller().getSelectionOffsets().start());
804 EXPECT_EQ(3u, controller().getSelectionOffsets().end()); 866 EXPECT_EQ(3u, controller().getSelectionOffsets().end());
805 } 867 }
806 868
807 TEST_F(InputMethodControllerTest, CompositionInputEventIsComposing) { 869 TEST_F(InputMethodControllerTest, CompositionInputEventIsComposing) {
808 document().settings()->setScriptEnabled(true); 870 document().settings()->setScriptEnabled(true);
809 Element* editable = insertHTMLElement( 871 Element* editable =
810 "<div id='sample' contentEditable='true'></div>", "sample"); 872 insertHTMLElement("<div id='sample' contenteditable></div>", "sample");
811 Element* script = document().createElement("script"); 873 Element* script = document().createElement("script");
812 script->setInnerHTML( 874 script->setInnerHTML(
813 "document.getElementById('sample').addEventListener('beforeinput', " 875 "document.getElementById('sample').addEventListener('beforeinput', "
814 "function(event) {" 876 " event => document.title = "
815 " document.title = `beforeinput.isComposing:${event.isComposing};`;" 877 " `beforeinput.isComposing:${event.isComposing};`);"
816 "});"
817 "document.getElementById('sample').addEventListener('input', " 878 "document.getElementById('sample').addEventListener('input', "
818 "function(event) {" 879 " event => document.title += "
819 " document.title += `input.isComposing:${event.isComposing};`;" 880 " `input.isComposing:${event.isComposing};`);");
820 "});");
821 document().body()->appendChild(script); 881 document().body()->appendChild(script);
822 document().view()->updateAllLifecyclePhases(); 882 document().view()->updateAllLifecyclePhases();
823 883
824 // Simulate composition in the |contentEditable|. 884 // Simulate composition in the |contentEditable|.
825 Vector<CompositionUnderline> underlines; 885 Vector<CompositionUnderline> underlines;
826 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 886 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
827 editable->focus(); 887 editable->focus();
828 888
829 document().setTitle(emptyString()); 889 document().setTitle(emptyString());
830 controller().setComposition("foo", underlines, 0, 3); 890 controller().setComposition("foo", underlines, 0, 3);
831 EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;", 891 EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;",
832 document().title().utf8().data()); 892 document().title().utf8().data());
833 893
834 document().setTitle(emptyString()); 894 document().setTitle(emptyString());
835 controller().finishComposingText(InputMethodController::KeepSelection); 895 controller().finishComposingText(InputMethodController::KeepSelection);
836 // Last pair of InputEvent should also be inside composition scope. 896 // Last pair of InputEvent should also be inside composition scope.
837 EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;", 897 EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;",
838 document().title().utf8().data()); 898 document().title().utf8().data());
839 } 899 }
840 900
841 TEST_F(InputMethodControllerTest, CompositionInputEventData) { 901 TEST_F(InputMethodControllerTest, CompositionInputEventForReplace) {
842 document().settings()->setScriptEnabled(true); 902 createHTMLWithCompositionInputEventListeners();
843 Element* editable = insertHTMLElement(
844 "<div id='sample' contentEditable='true'></div>", "sample");
845 Element* script = document().createElement("script");
846 script->setInnerHTML(
847 "document.getElementById('sample').addEventListener('beforeinput', "
848 "function(event) {"
849 " document.title = `beforeinput.data:${event.data};`;"
850 "});"
851 "document.getElementById('sample').addEventListener('input', "
852 "function(event) {"
853 " document.title += `input.data:${event.data};`;"
854 "});");
855 document().body()->appendChild(script);
856 document().view()->updateAllLifecyclePhases();
857 903
858 // Simulate composition in the |contentEditable|. 904 // Simulate composition in the |contentEditable|.
859 Vector<CompositionUnderline> underlines; 905 Vector<CompositionUnderline> underlines;
860 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 906 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
861 editable->focus();
862 907
863 document().setTitle(emptyString()); 908 document().setTitle(emptyString());
864 controller().setComposition("n", underlines, 0, 1); 909 controller().setComposition("hell", underlines, 4, 4);
910 EXPECT_STREQ("beforeinput.data:hell;input.data:hell;",
911 document().title().utf8().data());
912
913 // Replace the existing composition.
914 // TODO(yabinh): should be "beforeinput.data:hello;input.data:hello;".
915 document().setTitle(emptyString());
916 controller().setComposition("hello", underlines, 0, 0);
917 EXPECT_STREQ("beforeinput.data:o;input.data:o;",
918 document().title().utf8().data());
919 }
920
921 TEST_F(InputMethodControllerTest, CompositionInputEventForConfirm) {
922 createHTMLWithCompositionInputEventListeners();
923
924 // Simulate composition in the |contentEditable|.
925 Vector<CompositionUnderline> underlines;
926 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
927
928 document().setTitle(emptyString());
929 controller().setComposition("hello", underlines, 5, 5);
930 EXPECT_STREQ("beforeinput.data:hello;input.data:hello;",
931 document().title().utf8().data());
932
933 // Confirm the ongoing composition.
934 document().setTitle(emptyString());
935 controller().finishComposingText(InputMethodController::KeepSelection);
936 EXPECT_STREQ(
937 "beforeinput.data:hello;input.data:hello;compositionend.data:hello;",
938 document().title().utf8().data());
939 }
940
941 TEST_F(InputMethodControllerTest, CompositionInputEventForDelete) {
942 createHTMLWithCompositionInputEventListeners();
943
944 // Simulate composition in the |contentEditable|.
945 Vector<CompositionUnderline> underlines;
946 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
947
948 document().setTitle(emptyString());
949 controller().setComposition("hello", underlines, 5, 5);
950 EXPECT_STREQ("beforeinput.data:hello;input.data:hello;",
951 document().title().utf8().data());
952
953 // Delete the existing composition.
954 document().setTitle(emptyString());
955 controller().setComposition("", underlines, 0, 0);
956 EXPECT_STREQ("beforeinput.data:;compositionend.data:;",
957 document().title().utf8().data());
958 }
959
960 TEST_F(InputMethodControllerTest, CompositionInputEventForInsert) {
961 createHTMLWithCompositionInputEventListeners();
962
963 // Simulate composition in the |contentEditable|.
964 Vector<CompositionUnderline> underlines;
965 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
966
967 // Insert new text without previous composition.
968 document().setTitle(emptyString());
969 document().updateStyleAndLayout();
970 controller().commitText("hello", 0);
971 EXPECT_STREQ("beforeinput.data:hello;input.data:hello;",
972 document().title().utf8().data());
973
974 document().setTitle(emptyString());
975 controller().setComposition("n", underlines, 1, 1);
865 EXPECT_STREQ("beforeinput.data:n;input.data:n;", 976 EXPECT_STREQ("beforeinput.data:n;input.data:n;",
866 document().title().utf8().data()); 977 document().title().utf8().data());
867 978
979 // Insert new text with previous composition.
868 document().setTitle(emptyString()); 980 document().setTitle(emptyString());
869 controller().setComposition("ni", underlines, 0, 1); 981 document().updateStyleAndLayout();
870 EXPECT_STREQ("beforeinput.data:i;input.data:i;", 982 controller().commitText("hello", 1);
871 document().title().utf8().data()); 983 EXPECT_STREQ(
984 "beforeinput.data:hello;input.data:hello;compositionend.data:hello;",
985 document().title().utf8().data());
986 }
872 987
873 document().setTitle(emptyString()); 988 TEST_F(InputMethodControllerTest, CompositionEndEventForConfirm) {
874 controller().finishComposingText(InputMethodController::KeepSelection); 989 createHTMLWithCompositionEndEventListener(CaretSelection);
875 EXPECT_STREQ("beforeinput.data:ni;input.data:ni;", 990
876 document().title().utf8().data()); 991 // Simulate composition in the |contentEditable|.
992 Vector<CompositionUnderline> underlines;
993 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
994
995 controller().setComposition("hello", underlines, 1, 1);
996 document().updateStyleAndLayout();
997 EXPECT_EQ(1u, controller().getSelectionOffsets().start());
998 EXPECT_EQ(1u, controller().getSelectionOffsets().end());
999
1000 // Confirm the ongoing composition. Note that it moves the caret to the end of
1001 // text [5,5] before firing 'compositonend' event.
1002 controller().finishComposingText(InputMethodController::DoNotKeepSelection);
1003 document().updateStyleAndLayout();
1004 EXPECT_EQ(3u, controller().getSelectionOffsets().start());
1005 EXPECT_EQ(3u, controller().getSelectionOffsets().end());
1006 }
1007
1008 TEST_F(InputMethodControllerTest, CompositionEndEventForInsert) {
1009 createHTMLWithCompositionEndEventListener(CaretSelection);
1010
1011 // Simulate composition in the |contentEditable|.
1012 Vector<CompositionUnderline> underlines;
1013 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
1014
1015 controller().setComposition("n", underlines, 1, 1);
1016
1017 // Insert new text with previous composition. Note that it moves the caret to
1018 // [4,4] before firing 'compositonend' event.
1019 document().updateStyleAndLayout();
1020 controller().commitText("hello", -1);
1021 document().updateStyleAndLayout();
1022 EXPECT_EQ(3u, controller().getSelectionOffsets().start());
1023 EXPECT_EQ(3u, controller().getSelectionOffsets().end());
1024 }
1025
1026 TEST_F(InputMethodControllerTest, CompositionEndEventWithRangeSelection) {
1027 createHTMLWithCompositionEndEventListener(RangeSelection);
1028
1029 // Simulate composition in the |contentEditable|.
1030 Vector<CompositionUnderline> underlines;
1031 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
1032
1033 controller().setComposition("hello", underlines, 1, 1);
1034 document().updateStyleAndLayout();
1035 EXPECT_EQ(1u, controller().getSelectionOffsets().start());
1036 EXPECT_EQ(1u, controller().getSelectionOffsets().end());
1037
1038 // Confirm the ongoing composition. Note that it moves the caret to the end of
1039 // text [5,5] before firing 'compositonend' event.
1040 controller().finishComposingText(InputMethodController::DoNotKeepSelection);
1041 document().updateStyleAndLayout();
1042 EXPECT_EQ(2u, controller().getSelectionOffsets().start());
1043 EXPECT_EQ(4u, controller().getSelectionOffsets().end());
1044 }
1045
1046 TEST_F(InputMethodControllerTest, CompositionEndEventWithNoSelection) {
1047 createHTMLWithCompositionEndEventListener(NoSelection);
1048
1049 // Simulate composition in the |contentEditable|.
1050 Vector<CompositionUnderline> underlines;
1051 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
1052
1053 controller().setComposition("hello", underlines, 1, 1);
1054 document().updateStyleAndLayout();
1055 EXPECT_EQ(1u, controller().getSelectionOffsets().start());
1056 EXPECT_EQ(1u, controller().getSelectionOffsets().end());
1057
1058 // Confirm the ongoing composition. Note that it moves the caret to the end of
1059 // text [5,5] before firing 'compositonend' event.
1060 controller().finishComposingText(InputMethodController::DoNotKeepSelection);
1061 document().updateStyleAndLayout();
1062 EXPECT_TRUE(controller().getSelectionOffsets().isNull());
877 } 1063 }
878 1064
879 } // namespace blink 1065 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698