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