1197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// found in the LICENSE file. 4197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 5197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "config.h" 6197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/editing/InputMethodController.h" 7197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 8197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/dom/Element.h" 9197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/dom/Range.h" 10197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/frame/LocalFrame.h" 11197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/html/HTMLDocument.h" 12197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/html/HTMLInputElement.h" 13197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/testing/DummyPageHolder.h" 14197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include <gtest/gtest.h> 15197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 16197021e6b966cfb06891637935ef33fff06433d1Ben Murdochusing namespace blink; 17197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 18197021e6b966cfb06891637935ef33fff06433d1Ben Murdochnamespace { 19197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 20197021e6b966cfb06891637935ef33fff06433d1Ben Murdochclass InputMethodControllerTest : public ::testing::Test { 21197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprotected: 22197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch InputMethodController& controller() { return frame().inputMethodController(); } 23197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLDocument& document() const { return *m_document; } 24197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch LocalFrame& frame() const { return m_dummyPageHolder->frame(); } 25197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Element* insertHTMLElement(const char* elementCode, const char* elementId); 26197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 27197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate: 28197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch virtual void SetUp() OVERRIDE; 29197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 30197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch OwnPtr<DummyPageHolder> m_dummyPageHolder; 31197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLDocument* m_document; 32197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}; 33197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 34197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid InputMethodControllerTest::SetUp() 35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 36197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); 37197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_document = toHTMLDocument(&m_dummyPageHolder->document()); 38197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ASSERT(m_document); 39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 40197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 41197021e6b966cfb06891637935ef33fff06433d1Ben MurdochElement* InputMethodControllerTest::insertHTMLElement( 42197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch const char* elementCode, const char* elementId) 43197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 44197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch document().write(elementCode); 45197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch document().updateLayout(); 46197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Element* element = document().getElementById(elementId); 47197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch element->focus(); 48197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return element; 49197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 50197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 51197021e6b966cfb06891637935ef33fff06433d1Ben MurdochTEST_F(InputMethodControllerTest, BackspaceFromEndOfInput) 52197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 53197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLInputElement* input = toHTMLInputElement( 54197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch insertHTMLElement("<input id='sample'>", "sample")); 55197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 56197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch input->setValue("fooX"); 57197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); 58197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_STREQ("fooX", input->value().utf8().data()); 59c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) controller().extendSelectionAndDelete(0, 0); 60c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) EXPECT_STREQ("fooX", input->value().utf8().data()); 61c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 62c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) input->setValue("fooX"); 63c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); 64c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) EXPECT_STREQ("fooX", input->value().utf8().data()); 65197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().extendSelectionAndDelete(1, 0); 66197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_STREQ("foo", input->value().utf8().data()); 67197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 68197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch input->setValue(String::fromUTF8("foo\xE2\x98\x85")); // U+2605 == "black star" 69197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); 70197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_STREQ("foo\xE2\x98\x85", input->value().utf8().data()); 71197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().extendSelectionAndDelete(1, 0); 72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_STREQ("foo", input->value().utf8().data()); 73197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 74197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch input->setValue(String::fromUTF8("foo\xF0\x9F\x8F\x86")); // U+1F3C6 == "trophy" 75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); 76197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_STREQ("foo\xF0\x9F\x8F\x86", input->value().utf8().data()); 77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().extendSelectionAndDelete(1, 0); 78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_STREQ("foo", input->value().utf8().data()); 79197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 80197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch input->setValue(String::fromUTF8("foo\xE0\xB8\x81\xE0\xB9\x89")); // composed U+0E01 "ka kai" + U+0E49 "mai tho" 81197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); 82197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_STREQ("foo\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data()); 83197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().extendSelectionAndDelete(1, 0); 84197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_STREQ("foo", input->value().utf8().data()); 85c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 86c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) input->setValue("fooX"); 87c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); 88c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) EXPECT_STREQ("fooX", input->value().utf8().data()); 89c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) controller().extendSelectionAndDelete(0, 1); 90c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) EXPECT_STREQ("fooX", input->value().utf8().data()); 91197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 92197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 93197021e6b966cfb06891637935ef33fff06433d1Ben MurdochTEST_F(InputMethodControllerTest, SetCompositionFromExistingText) 94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 95197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Element* div = insertHTMLElement( 96197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch "<div id='sample' contenteditable='true'>hello world</div>", "sample"); 97197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 98197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Vector<CompositionUnderline> underlines; 99197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 100197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().setCompositionFromExistingText(underlines, 0, 5); 101197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 102197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch RefPtrWillBeRawPtr<Range> range = controller().compositionRange(); 103197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(0, range->startOffset()); 104197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(5, range->endOffset()); 105197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 106197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch PlainTextRange plainTextRange(PlainTextRange::create(*div, *range.get())); 107197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(0u, plainTextRange.start()); 108197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(5u, plainTextRange.end()); 109197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 110197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 111197021e6b966cfb06891637935ef33fff06433d1Ben MurdochTEST_F(InputMethodControllerTest, SetCompositionFromExistingTextWithCollapsedWhiteSpace) 112197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 113197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Creates a div with one leading new line char. The new line char is hidden 114197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // from the user and IME, but is visible to InputMethodController. 115197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Element* div = insertHTMLElement( 116197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch "<div id='sample' contenteditable='true'>\nhello world</div>", "sample"); 117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 118197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Vector<CompositionUnderline> underlines; 119197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 120197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch controller().setCompositionFromExistingText(underlines, 0, 5); 121197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 122197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch RefPtrWillBeRawPtr<Range> range = controller().compositionRange(); 123197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(1, range->startOffset()); 124197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(6, range->endOffset()); 125197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 126197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch PlainTextRange plainTextRange(PlainTextRange::create(*div, *range.get())); 127197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(0u, plainTextRange.start()); 128197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(5u, plainTextRange.end()); 129197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 130197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 1317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciTEST_F(InputMethodControllerTest, SetCompositionFromExistingTextWithInvalidOffsets) 1327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 1337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci insertHTMLElement("<div id='sample' contenteditable='true'>test</div>", "sample"); 1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Vector<CompositionUnderline> underlines; 1367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci underlines.append(CompositionUnderline(7, 8, Color(255, 0, 0), false, 0)); 1377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci controller().setCompositionFromExistingText(underlines, 7, 8); 1387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_FALSE(controller().compositionRange()); 1407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 1417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 142197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} // namespace 143