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
3 // found in the LICENSE file.
6 #include "core/editing/InputMethodController.h"
8 #include "core/dom/Element.h"
9 #include "core/dom/Range.h"
10 #include "core/frame/LocalFrame.h"
11 #include "core/html/HTMLDocument.h"
12 #include "core/html/HTMLInputElement.h"
13 #include "core/testing/DummyPageHolder.h"
14 #include <gtest/gtest.h>
16 using namespace blink;
17 using namespace blink;
21 class InputMethodControllerTest : public ::testing::Test {
23 InputMethodController& controller() { return frame().inputMethodController(); }
24 HTMLDocument& document() const { return *m_document; }
25 LocalFrame& frame() const { return m_dummyPageHolder->frame(); }
26 Element* insertHTMLElement(const char* elementCode, const char* elementId);
29 virtual void SetUp() OVERRIDE;
31 OwnPtr<DummyPageHolder> m_dummyPageHolder;
32 HTMLDocument* m_document;
35 void InputMethodControllerTest::SetUp()
37 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600));
38 m_document = toHTMLDocument(&m_dummyPageHolder->document());
42 Element* InputMethodControllerTest::insertHTMLElement(
43 const char* elementCode, const char* elementId)
45 document().write(elementCode);
46 document().updateLayout();
47 Element* element = document().getElementById(elementId);
52 TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput)
54 HTMLInputElement* input = toHTMLInputElement(
55 insertHTMLElement("<input id='sample'>", "sample"));
57 input->setValue("fooX");
58 controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
59 EXPECT_STREQ("fooX", input->value().utf8().data());
60 controller().extendSelectionAndDelete(0, 0);
61 EXPECT_STREQ("fooX", input->value().utf8().data());
63 input->setValue("fooX");
64 controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
65 EXPECT_STREQ("fooX", input->value().utf8().data());
66 controller().extendSelectionAndDelete(1, 0);
67 EXPECT_STREQ("foo", input->value().utf8().data());
69 input->setValue(String::fromUTF8("foo\xE2\x98\x85")); // U+2605 == "black star"
70 controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
71 EXPECT_STREQ("foo\xE2\x98\x85", input->value().utf8().data());
72 controller().extendSelectionAndDelete(1, 0);
73 EXPECT_STREQ("foo", input->value().utf8().data());
75 input->setValue(String::fromUTF8("foo\xF0\x9F\x8F\x86")); // U+1F3C6 == "trophy"
76 controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
77 EXPECT_STREQ("foo\xF0\x9F\x8F\x86", input->value().utf8().data());
78 controller().extendSelectionAndDelete(1, 0);
79 EXPECT_STREQ("foo", input->value().utf8().data());
81 input->setValue(String::fromUTF8("foo\xE0\xB8\x81\xE0\xB9\x89")); // composed U+0E01 "ka kai" + U+0E49 "mai tho"
82 controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
83 EXPECT_STREQ("foo\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data());
84 controller().extendSelectionAndDelete(1, 0);
85 EXPECT_STREQ("foo", input->value().utf8().data());
87 input->setValue("fooX");
88 controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
89 EXPECT_STREQ("fooX", input->value().utf8().data());
90 controller().extendSelectionAndDelete(0, 1);
91 EXPECT_STREQ("fooX", input->value().utf8().data());
94 TEST_F(InputMethodControllerTest, SetCompositionFromExistingText)
96 Element* div = insertHTMLElement(
97 "<div id='sample' contenteditable='true'>hello world</div>", "sample");
99 Vector<CompositionUnderline> underlines;
100 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
101 controller().setCompositionFromExistingText(underlines, 0, 5);
103 RefPtrWillBeRawPtr<Range> range = controller().compositionRange();
104 EXPECT_EQ(0, range->startOffset());
105 EXPECT_EQ(5, range->endOffset());
107 PlainTextRange plainTextRange(PlainTextRange::create(*div, *range.get()));
108 EXPECT_EQ(0u, plainTextRange.start());
109 EXPECT_EQ(5u, plainTextRange.end());
112 TEST_F(InputMethodControllerTest, SetCompositionFromExistingTextWithCollapsedWhiteSpace)
114 // Creates a div with one leading new line char. The new line char is hidden
115 // from the user and IME, but is visible to InputMethodController.
116 Element* div = insertHTMLElement(
117 "<div id='sample' contenteditable='true'>\nhello world</div>", "sample");
119 Vector<CompositionUnderline> underlines;
120 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
121 controller().setCompositionFromExistingText(underlines, 0, 5);
123 RefPtrWillBeRawPtr<Range> range = controller().compositionRange();
124 EXPECT_EQ(1, range->startOffset());
125 EXPECT_EQ(6, range->endOffset());
127 PlainTextRange plainTextRange(PlainTextRange::create(*div, *range.get()));
128 EXPECT_EQ(0u, plainTextRange.start());
129 EXPECT_EQ(5u, plainTextRange.end());
132 TEST_F(InputMethodControllerTest, SetCompositionFromExistingTextWithInvalidOffsets)
134 insertHTMLElement("<div id='sample' contenteditable='true'>test</div>", "sample");
136 Vector<CompositionUnderline> underlines;
137 underlines.append(CompositionUnderline(7, 8, Color(255, 0, 0), false, 0));
138 controller().setCompositionFromExistingText(underlines, 7, 8);
140 EXPECT_FALSE(controller().compositionRange());