blob: cf3a678af51aa15ce29bd8ab60872f35ec238646 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/editing/InputMethodController.h"
#include "core/dom/Element.h"
#include "core/dom/Range.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLDocument.h"
#include "core/html/HTMLInputElement.h"
#include "core/testing/DummyPageHolder.h"
#include <gtest/gtest.h>
using namespace blink;
using namespace blink;
namespace {
class InputMethodControllerTest : public ::testing::Test {
protected:
InputMethodController& controller() { return frame().inputMethodController(); }
HTMLDocument& document() const { return *m_document; }
LocalFrame& frame() const { return m_dummyPageHolder->frame(); }
Element* insertHTMLElement(const char* elementCode, const char* elementId);
private:
virtual void SetUp() OVERRIDE;
OwnPtr<DummyPageHolder> m_dummyPageHolder;
HTMLDocument* m_document;
};
void InputMethodControllerTest::SetUp()
{
m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600));
m_document = toHTMLDocument(&m_dummyPageHolder->document());
ASSERT(m_document);
}
Element* InputMethodControllerTest::insertHTMLElement(
const char* elementCode, const char* elementId)
{
document().write(elementCode);
document().updateLayout();
Element* element = document().getElementById(elementId);
element->focus();
return element;
}
TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput)
{
HTMLInputElement* input = toHTMLInputElement(
insertHTMLElement("<input id='sample'>", "sample"));
input->setValue("fooX");
controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
EXPECT_STREQ("fooX", input->value().utf8().data());
controller().extendSelectionAndDelete(0, 0);
EXPECT_STREQ("fooX", input->value().utf8().data());
input->setValue("fooX");
controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
EXPECT_STREQ("fooX", input->value().utf8().data());
controller().extendSelectionAndDelete(1, 0);
EXPECT_STREQ("foo", input->value().utf8().data());
input->setValue(String::fromUTF8("foo\xE2\x98\x85")); // U+2605 == "black star"
controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
EXPECT_STREQ("foo\xE2\x98\x85", input->value().utf8().data());
controller().extendSelectionAndDelete(1, 0);
EXPECT_STREQ("foo", input->value().utf8().data());
input->setValue(String::fromUTF8("foo\xF0\x9F\x8F\x86")); // U+1F3C6 == "trophy"
controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
EXPECT_STREQ("foo\xF0\x9F\x8F\x86", input->value().utf8().data());
controller().extendSelectionAndDelete(1, 0);
EXPECT_STREQ("foo", input->value().utf8().data());
input->setValue(String::fromUTF8("foo\xE0\xB8\x81\xE0\xB9\x89")); // composed U+0E01 "ka kai" + U+0E49 "mai tho"
controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
EXPECT_STREQ("foo\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data());
controller().extendSelectionAndDelete(1, 0);
EXPECT_STREQ("foo", input->value().utf8().data());
input->setValue("fooX");
controller().setEditableSelectionOffsets(PlainTextRange(4, 4));
EXPECT_STREQ("fooX", input->value().utf8().data());
controller().extendSelectionAndDelete(0, 1);
EXPECT_STREQ("fooX", input->value().utf8().data());
}
TEST_F(InputMethodControllerTest, SetCompositionFromExistingText)
{
Element* div = insertHTMLElement(
"<div id='sample' contenteditable='true'>hello world</div>", "sample");
Vector<CompositionUnderline> underlines;
underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
controller().setCompositionFromExistingText(underlines, 0, 5);
RefPtrWillBeRawPtr<Range> range = controller().compositionRange();
EXPECT_EQ(0, range->startOffset());
EXPECT_EQ(5, range->endOffset());
PlainTextRange plainTextRange(PlainTextRange::create(*div, *range.get()));
EXPECT_EQ(0u, plainTextRange.start());
EXPECT_EQ(5u, plainTextRange.end());
}
TEST_F(InputMethodControllerTest, SetCompositionFromExistingTextWithCollapsedWhiteSpace)
{
// Creates a div with one leading new line char. The new line char is hidden
// from the user and IME, but is visible to InputMethodController.
Element* div = insertHTMLElement(
"<div id='sample' contenteditable='true'>\nhello world</div>", "sample");
Vector<CompositionUnderline> underlines;
underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
controller().setCompositionFromExistingText(underlines, 0, 5);
RefPtrWillBeRawPtr<Range> range = controller().compositionRange();
EXPECT_EQ(1, range->startOffset());
EXPECT_EQ(6, range->endOffset());
PlainTextRange plainTextRange(PlainTextRange::create(*div, *range.get()));
EXPECT_EQ(0u, plainTextRange.start());
EXPECT_EQ(5u, plainTextRange.end());
}
TEST_F(InputMethodControllerTest, SetCompositionFromExistingTextWithInvalidOffsets)
{
insertHTMLElement("<div id='sample' contenteditable='true'>test</div>", "sample");
Vector<CompositionUnderline> underlines;
underlines.append(CompositionUnderline(7, 8, Color(255, 0, 0), false, 0));
controller().setCompositionFromExistingText(underlines, 7, 8);
EXPECT_FALSE(controller().compositionRange());
}
} // namespace