Index: Source/core/html/HTMLTextFormControlElementTest.cpp |
diff --git a/Source/core/html/HTMLTextFormControlElementTest.cpp b/Source/core/html/HTMLTextFormControlElementTest.cpp |
index 1134854814f50e622791d248eed837aa2d9c7b0b..10f35e0b7f530de6fb6f8d97968cc126cfc3262e 100644 |
--- a/Source/core/html/HTMLTextFormControlElementTest.cpp |
+++ b/Source/core/html/HTMLTextFormControlElementTest.cpp |
@@ -5,12 +5,25 @@ |
#include "config.h" |
#include "core/html/HTMLTextFormControlElement.h" |
+#include "core/dom/Position.h" |
+#include "core/dom/Text.h" |
+#include "core/editing/FrameSelection.h" |
+#include "core/editing/SpellChecker.h" |
+#include "core/editing/VisibleSelection.h" |
+#include "core/editing/VisibleUnits.h" |
#include "core/frame/FrameView.h" |
+#include "core/html/HTMLBRElement.h" |
#include "core/html/HTMLDocument.h" |
+#include "core/html/HTMLInputElement.h" |
+#include "core/html/HTMLTextAreaElement.h" |
+#include "core/page/SpellCheckerClient.h" |
+#include "core/rendering/RenderTreeAsText.h" |
#include "core/testing/DummyPageHolder.h" |
+#include "platform/text/TextCheckerClient.h" |
#include "wtf/OwnPtr.h" |
#include <gtest/gtest.h> |
+using namespace blink; |
using namespace WebCore; |
namespace { |
@@ -19,21 +32,33 @@ class HTMLTextFormControlElementTest : public ::testing::Test { |
protected: |
virtual void SetUp() OVERRIDE; |
+ void SetUpWithPageClients(Page::PageClients*); |
+ |
+ DummyPageHolder& page() const { return *m_dummyPageHolder; } |
+ HTMLDocument& document() const { return *m_document; } |
HTMLTextFormControlElement& textControl() const { return *m_textControl; } |
private: |
OwnPtr<DummyPageHolder> m_dummyPageHolder; |
+ RefPtrWillBePersistent<HTMLDocument> m_document; |
RefPtrWillBePersistent<HTMLTextFormControlElement> m_textControl; |
}; |
void HTMLTextFormControlElementTest::SetUp() |
{ |
- m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); |
- HTMLDocument& document = toHTMLDocument(m_dummyPageHolder->document()); |
- document.documentElement()->setInnerHTML("<body><textarea id=textarea></textarea></body>", ASSERT_NO_EXCEPTION); |
- document.view()->updateLayoutAndStyleIfNeededRecursive(); |
- m_textControl = toHTMLTextFormControlElement(document.getElementById("textarea")); |
+ Page::PageClients pageClients; |
+ fillWithEmptyClients(pageClients); |
+ SetUpWithPageClients(&pageClients); |
+} |
+ |
+void HTMLTextFormControlElementTest::SetUpWithPageClients(Page::PageClients* pageClients) |
+{ |
+ m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600), pageClients); |
+ m_document = toHTMLDocument(&m_dummyPageHolder->document()); |
+ m_document->documentElement()->setInnerHTML("<body><textarea id=textarea></textarea><input id=input /></body>", ASSERT_NO_EXCEPTION); |
+ m_document->view()->updateLayoutAndStyleIfNeededRecursive(); |
+ m_textControl = toHTMLTextFormControlElement(m_document->getElementById("textarea")); |
m_textControl->focus(); |
} |
@@ -51,4 +76,121 @@ TEST_F(HTMLTextFormControlElementTest, SetSelectionRange) |
EXPECT_EQ(3, textControl().selectionEnd()); |
} |
+typedef Position (*PositionFunction)(const Position&); |
+typedef VisiblePosition(*VisblePositionFunction)(const VisiblePosition&); |
+ |
+void testFunctionEquality(const Position& position, PositionFunction positionFunction, VisblePositionFunction visibleFunction) |
+{ |
+ VisiblePosition visiblePosition(position); |
+ VisiblePosition expected = visibleFunction(visiblePosition); |
+ VisiblePosition actual = VisiblePosition(positionFunction(position)); |
+ EXPECT_EQ(expected, actual); |
+} |
+ |
+static VisiblePosition startOfWord(const VisiblePosition& position) |
+{ |
+ return startOfWord(position, LeftWordIfOnBoundary); |
+} |
+ |
+static VisiblePosition endOfWord(const VisiblePosition& position) |
+{ |
+ return endOfWord(position, RightWordIfOnBoundary); |
+} |
+ |
+TEST_F(HTMLTextFormControlElementTest, WordAndSentenceBoundary) |
+{ |
+ HTMLElement* innerText = textControl().innerEditorElement(); |
+ // We have: |
+ // innerText(shadow root) |
+ // --#Text "Hello, text form." |
+ // --BR |
+ // --BR |
+ // --#TEXT "" |
+ // --#TEXT "\n\n" |
+ // --#TEXT "\n" |
+ // --#Text "Hel\nlo, te" |
+ // --#TEXT "xt form." |
+ innerText->appendChild(Text::create(document(), "Hello, text form.")); |
+ innerText->appendChild(HTMLBRElement::create(document())); |
+ innerText->appendChild(HTMLBRElement::create(document())); |
+ innerText->appendChild(Text::create(document(), "")); |
+ innerText->appendChild(Text::create(document(), "\n\n")); |
+ innerText->appendChild(Text::create(document(), "\n")); |
+ innerText->appendChild(Text::create(document(), "Hel\nlo, te")); |
+ innerText->appendChild(Text::create(document(), "xt form.")); |
+ |
+ for (unsigned i = 0; i < textControl().innerEditorValue().length(); i++) { |
+ textControl().setSelectionRange(i, i); |
+ Position pos = document().frame()->selection().start(); |
+ SCOPED_TRACE(testing::Message() << "offset " << pos.deprecatedEditingOffset() << " of " << nodePosition(pos.deprecatedNode()).ascii().data()); |
+ { |
+ SCOPED_TRACE("HTMLTextFormControlElement::startOfWord"); |
+ testFunctionEquality(pos, HTMLTextFormControlElement::startOfWord, startOfWord); |
+ } |
+ { |
+ SCOPED_TRACE("HTMLTextFormControlElement::endOfWord"); |
+ testFunctionEquality(pos, HTMLTextFormControlElement::endOfWord, endOfWord); |
+ } |
+ { |
+ SCOPED_TRACE("HTMLTextFormControlElement::startOfSentence"); |
+ testFunctionEquality(pos, HTMLTextFormControlElement::startOfSentence, startOfSentence); |
+ } |
+ { |
+ SCOPED_TRACE("HTMLTextFormControlElement::endOfSentence"); |
+ testFunctionEquality(pos, HTMLTextFormControlElement::endOfSentence, endOfSentence); |
+ } |
+ } |
+} |
+ |
+class DummyTextCheckerClient : public TextCheckerClient { |
+public: |
+ virtual bool shouldEraseMarkersAfterChangeSelection(TextCheckingType type) const OVERRIDE { return false; } |
+ virtual void checkSpellingOfString(const String&, int* misspellingLocation, int* misspellingLength) OVERRIDE { } |
+ virtual String getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord) OVERRIDE { return String(); } |
+ virtual void checkGrammarOfString(const String&, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) OVERRIDE { } |
+ virtual void requestCheckingOfString(PassRefPtr<TextCheckingRequest>) OVERRIDE { } |
+}; |
+ |
+class DummySpellCheckerClient : public SpellCheckerClient { |
+public: |
+ DummySpellCheckerClient() : m_textChecker(adoptPtr(new DummyTextCheckerClient)) { } |
+ virtual bool isContinuousSpellCheckingEnabled() OVERRIDE { return true; } |
+ virtual void toggleContinuousSpellChecking() OVERRIDE { } |
+ virtual bool isGrammarCheckingEnabled() OVERRIDE { return true; } |
+ |
+ virtual TextCheckerClient& textChecker() OVERRIDE { return *m_textChecker; } |
+ |
+ virtual void updateSpellingUIWithMisspelledWord(const WTF::String&) OVERRIDE { } |
+ virtual void showSpellingUI(bool show) OVERRIDE { } |
+ virtual bool spellingUIIsShowing() OVERRIDE { return true; } |
+ |
+ OwnPtr<TextCheckerClient> m_textChecker; |
+}; |
+ |
+ |
+TEST_F(HTMLTextFormControlElementTest, SpellCheckDoesNotCauseUpdateLayout) |
+{ |
+ Page::PageClients pageClients; |
+ fillWithEmptyClients(pageClients); |
+ static SpellCheckerClient* dummySpellCheckerClient = adoptPtr(new DummySpellCheckerClient).leakPtr(); |
+ pageClients.spellCheckerClient = dummySpellCheckerClient; |
+ SetUpWithPageClients(&pageClients); |
+ |
+ HTMLInputElement* input = toHTMLInputElement(document().getElementById("input")); |
+ input->focus(); |
+ input->setValue("Hello, input field"); |
+ VisibleSelection oldSelection = document().frame()->selection().selection(); |
+ |
+ Position newPosition(input->innerEditorElement()->firstChild(), 3, Position::PositionIsOffsetInAnchor); |
+ VisibleSelection newSelection(newPosition, DOWNSTREAM); |
+ document().frame()->selection().setSelection(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | FrameSelection::DoNotUpdateAppearance); |
+ ASSERT_EQ(3, input->selectionStart()); |
+ |
+ OwnPtrWillBeRawPtr<SpellChecker> spellChecker(SpellChecker::create(page().frame())); |
+ page().frameView().setFrameRect(WebCore::IntRect(0, 0, 801, 601)); |
+ int startCount = page().frameView().layoutCount(); |
+ spellChecker->respondToChangedSelection(oldSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle); |
+ EXPECT_EQ(startCount, page().frameView().layoutCount()); |
+} |
+ |
} |