| Index: Source/core/editing/GranularityStrategyTest.cpp
|
| diff --git a/Source/core/editing/GranularityStrategyTest.cpp b/Source/core/editing/GranularityStrategyTest.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1cdaf711c8191a9eb36e7ba8a7aaa6e5175e4454
|
| --- /dev/null
|
| +++ b/Source/core/editing/GranularityStrategyTest.cpp
|
| @@ -0,0 +1,663 @@
|
| +// 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 "bindings/core/v8/ExceptionStatePlaceholder.h"
|
| +#include "core/HTMLNames.h"
|
| +#include "core/dom/Document.h"
|
| +#include "core/dom/Element.h"
|
| +#include "core/dom/Text.h"
|
| +#include "core/editing/FrameSelection.h"
|
| +#include "core/frame/FrameView.h"
|
| +#include "core/frame/Settings.h"
|
| +#include "core/html/HTMLBodyElement.h"
|
| +#include "core/html/HTMLDocument.h"
|
| +#include "core/testing/DummyPageHolder.h"
|
| +#include "wtf/OwnPtr.h"
|
| +#include "wtf/PassRefPtr.h"
|
| +#include "wtf/RefPtr.h"
|
| +#include "wtf/StdLibExtras.h"
|
| +#include "wtf/testing/WTFTestHelpers.h"
|
| +#include <gtest/gtest.h>
|
| +
|
| +using namespace blink;
|
| +
|
| +namespace {
|
| +
|
| +#define EXPECT_EQ_SELECTED_TEXT(text) \
|
| + EXPECT_EQ(text, WebString(selection().selectedText()).utf8())
|
| +
|
| +IntPoint visiblePositionToContentsPoint(const VisiblePosition& pos)
|
| +{
|
| + IntPoint result = pos.absoluteCaretBounds().minXMaxYCorner();
|
| + // Need to move the point at least by 1 - caret's minXMaxYCorner is not
|
| + // evaluated to the same line as the text by hit testing.
|
| + result.move(0, -1);
|
| + return result;
|
| +}
|
| +
|
| +class GranularityStrategyTest : public ::testing::Test {
|
| +protected:
|
| + virtual void SetUp() override;
|
| +
|
| + DummyPageHolder& dummyPageHolder() const { return *m_dummyPageHolder; }
|
| + HTMLDocument& document() const;
|
| + void setSelection(const VisibleSelection&);
|
| + FrameSelection& selection() const;
|
| + PassRefPtrWillBeRawPtr<Text> appendTextNode(const String& data);
|
| + int layoutCount() const { return m_dummyPageHolder->frameView().layoutCount(); }
|
| + void setInnerHTML(const char*);
|
| + // Parses the text node, appending the info to m_letterPos and m_wordMiddles.
|
| + void parseText(Text*);
|
| + void parseText(std::vector<Text*>);
|
| +
|
| + PassRefPtrWillBeRawPtr<Text> setupTranslateZ(WTF::String);
|
| + PassRefPtrWillBeRawPtr<Text> setupTransform(WTF::String);
|
| + PassRefPtrWillBeRawPtr<Text> setupRotate(WTF::String);
|
| + void setupTextSpan(WTF::String str1, WTF::String str2, WTF::String str3, size_t selBegin, size_t selEnd);
|
| + void setupVerticalAlign(WTF::String str1, WTF::String str2, WTF::String str3, size_t selBegin, size_t selEnd);
|
| + void setupFontSize(WTF::String str1, WTF::String str2, WTF::String str3, size_t selBegin, size_t selEnd);
|
| +
|
| + void testDirectionExpand();
|
| + void testDirectionShrink();
|
| + void testDirectionSwitchSide();
|
| +
|
| + // Pixel coordinates of the positions for each letter within the text being tested.
|
| + std::vector<IntPoint> m_letterPos;
|
| + // Pixel coordinates of the middles of the words in the text being tested.
|
| + // (y coordinate is based on y coordinates of m_letterPos)
|
| + std::vector<IntPoint> m_wordMiddles;
|
| +
|
| +private:
|
| + OwnPtr<DummyPageHolder> m_dummyPageHolder;
|
| + RawPtr<HTMLDocument> m_document;
|
| +};
|
| +
|
| +void GranularityStrategyTest::SetUp()
|
| +{
|
| + m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600));
|
| + m_document = toHTMLDocument(&m_dummyPageHolder->document());
|
| + ASSERT(m_document);
|
| + dummyPageHolder().frame().settings()->setDefaultFontSize(12);
|
| + dummyPageHolder().frame().settings()->setSelectionStrategy(SelectionStrategy::Direction);
|
| +}
|
| +
|
| +HTMLDocument& GranularityStrategyTest::document() const
|
| +{
|
| + return *m_document;
|
| +}
|
| +
|
| +void GranularityStrategyTest::setSelection(const VisibleSelection& newSelection)
|
| +{
|
| + m_dummyPageHolder->frame().selection().setSelection(newSelection);
|
| +}
|
| +
|
| +FrameSelection& GranularityStrategyTest::selection() const
|
| +{
|
| + return m_dummyPageHolder->frame().selection();
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<Text> GranularityStrategyTest::appendTextNode(const String& data)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text = document().createTextNode(data);
|
| + document().body()->appendChild(text);
|
| + return text.release();
|
| +}
|
| +
|
| +void GranularityStrategyTest::setInnerHTML(const char* htmlContent)
|
| +{
|
| + document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent), ASSERT_NO_EXCEPTION);
|
| + document().view()->updateLayoutAndStyleForPainting();
|
| +}
|
| +
|
| +void GranularityStrategyTest::parseText(Text* text)
|
| +{
|
| + std::vector<Text*> vec;
|
| + vec.push_back(text);
|
| + parseText(vec);
|
| +}
|
| +
|
| +void GranularityStrategyTest::parseText(std::vector<Text*> textNodes)
|
| +{
|
| + bool wordStarted = false;
|
| + int wordStartIndex = 0;
|
| + for (Text* text : textNodes) {
|
| + int wordStartIndexOffset = m_letterPos.size();
|
| + WTF::String str = text->wholeText();
|
| + for (size_t i = 0; i < str.length(); i++) {
|
| + m_letterPos.push_back(visiblePositionToContentsPoint(VisiblePosition(Position(text, i))));
|
| + char c = str.characterAt(i);
|
| + if (isASCIIAlphanumeric(c) && !wordStarted) {
|
| + wordStartIndex = i + wordStartIndexOffset;
|
| + wordStarted = true;
|
| + } else if (!isASCIIAlphanumeric(c) && wordStarted) {
|
| + IntPoint wordMiddle((m_letterPos[wordStartIndex].x() + m_letterPos[i + wordStartIndexOffset].x()) / 2, m_letterPos[wordStartIndex].y());
|
| + m_wordMiddles.push_back(wordMiddle);
|
| + wordStarted = false;
|
| + }
|
| + }
|
| + }
|
| + if (wordStarted) {
|
| + Text* lastNode = textNodes[textNodes.size() - 1];
|
| + int xEnd = visiblePositionToContentsPoint(VisiblePosition(Position(lastNode, lastNode->wholeText().length()))).x();
|
| + IntPoint wordMiddle((m_letterPos[wordStartIndex].x() + xEnd) / 2, m_letterPos[wordStartIndex].y());
|
| + m_wordMiddles.push_back(wordMiddle);
|
| + }
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<Text> GranularityStrategyTest::setupTranslateZ(WTF::String str)
|
| +{
|
| + setInnerHTML(
|
| + "<html>"
|
| + "<head>"
|
| + "<style>"
|
| + "div {"
|
| + "transform: translateZ(0);"
|
| + "}"
|
| + "</style>"
|
| + "</head>"
|
| + "<body>"
|
| + "<div id='mytext'></div>"
|
| + "</body>"
|
| + "</html>");
|
| +
|
| + RefPtrWillBeRawPtr<Text> text = document().createTextNode(str);
|
| + Element* div = document().getElementById("mytext");
|
| + div->appendChild(text);
|
| +
|
| + document().view()->updateLayoutAndStyleForPainting();
|
| +
|
| + parseText(text.get());
|
| + return text.release();
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<Text> GranularityStrategyTest::setupTransform(WTF::String str)
|
| +{
|
| + setInnerHTML(
|
| + "<html>"
|
| + "<head>"
|
| + "<style>"
|
| + "div {"
|
| + "transform: scale(1,-1) translate(0,-100px);"
|
| + "}"
|
| + "</style>"
|
| + "</head>"
|
| + "<body>"
|
| + "<div id='mytext'></div>"
|
| + "</body>"
|
| + "</html>");
|
| +
|
| + RefPtrWillBeRawPtr<Text> text = document().createTextNode(str);
|
| + Element* div = document().getElementById("mytext");
|
| + div->appendChild(text);
|
| +
|
| + document().view()->updateLayoutAndStyleForPainting();
|
| +
|
| + parseText(text.get());
|
| + return text.release();
|
| +}
|
| +
|
| +PassRefPtrWillBeRawPtr<Text> GranularityStrategyTest::setupRotate(WTF::String str)
|
| +{
|
| + setInnerHTML(
|
| + "<html>"
|
| + "<head>"
|
| + "<style>"
|
| + "div {"
|
| + "transform: translate(0px,600px) rotate(90deg);"
|
| + "}"
|
| + "</style>"
|
| + "</head>"
|
| + "<body>"
|
| + "<div id='mytext'></div>"
|
| + "</body>"
|
| + "</html>");
|
| +
|
| + RefPtrWillBeRawPtr<Text> text = document().createTextNode(str);
|
| + Element* div = document().getElementById("mytext");
|
| + div->appendChild(text);
|
| +
|
| + document().view()->updateLayoutAndStyleForPainting();
|
| +
|
| + parseText(text.get());
|
| + return text.release();
|
| +}
|
| +
|
| +void GranularityStrategyTest::setupTextSpan(WTF::String str1, WTF::String str2, WTF::String str3, size_t selBegin, size_t selEnd)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text1 = document().createTextNode(str1);
|
| + RefPtrWillBeRawPtr<Text> text2 = document().createTextNode(str2);
|
| + RefPtrWillBeRawPtr<Text> text3 = document().createTextNode(str3);
|
| + RefPtrWillBeRawPtr<Element> span = document().createElement(HTMLNames::spanTag, true);
|
| + Element* div = document().getElementById("mytext");
|
| + div->appendChild(text1);
|
| + div->appendChild(span);
|
| + span->appendChild(text2);
|
| + div->appendChild(text3);
|
| +
|
| + document().view()->updateLayoutAndStyleForPainting();
|
| +
|
| + std::vector<IntPoint> letterPos;
|
| + std::vector<IntPoint> wordMiddlePos;
|
| +
|
| + std::vector<Text*> textNodes;
|
| + textNodes.push_back(text1.get());
|
| + textNodes.push_back(text2.get());
|
| + textNodes.push_back(text3.get());
|
| + parseText(textNodes);
|
| +
|
| + Position p1;
|
| + Position p2;
|
| + if (selBegin < str1.length())
|
| + p1 = Position(text1, selBegin);
|
| + else if (selBegin < str1.length() + str2.length())
|
| + p1 = Position(text2, selBegin - str1.length());
|
| + else
|
| + p1 = Position(text3, selBegin - str1.length() - str2.length());
|
| + if (selEnd < str1.length())
|
| + p2 = Position(text1, selEnd);
|
| + else if (selEnd < str1.length() + str2.length())
|
| + p2 = Position(text2, selEnd - str1.length());
|
| + else
|
| + p2 = Position(text3, selEnd - str1.length() - str2.length());
|
| +
|
| + selection().setSelection(VisibleSelection(p1, p2));
|
| +}
|
| +
|
| +void GranularityStrategyTest::setupVerticalAlign(WTF::String str1, WTF::String str2, WTF::String str3, size_t selBegin, size_t selEnd)
|
| +{
|
| + setInnerHTML(
|
| + "<html>"
|
| + "<head>"
|
| + "<style>"
|
| + "span {"
|
| + "vertical-align:20px;"
|
| + "}"
|
| + "</style>"
|
| + "</head>"
|
| + "<body>"
|
| + "<div id='mytext'></div>"
|
| + "</body>"
|
| + "</html>");
|
| +
|
| + setupTextSpan(str1, str2, str3, selBegin, selEnd);
|
| +}
|
| +
|
| +void GranularityStrategyTest::setupFontSize(WTF::String str1, WTF::String str2, WTF::String str3, size_t selBegin, size_t selEnd)
|
| +{
|
| + setInnerHTML(
|
| + "<html>"
|
| + "<head>"
|
| + "<style>"
|
| + "span {"
|
| + "font-size: 200%;"
|
| + "}"
|
| + "</style>"
|
| + "</head>"
|
| + "<body>"
|
| + "<div id='mytext'></div>"
|
| + "</body>"
|
| + "</html>");
|
| +
|
| + setupTextSpan(str1, str2, str3, selBegin, selEnd);
|
| +}
|
| +
|
| +
|
| +// Tests expanding selection on text "abcdef ghij kl mno^p|>qr stuvwi inm mnii,"
|
| +// (^ means base, | means extent, < means start, and > means end).
|
| +// Text needs to be laid out on a single line with no rotation.
|
| +void GranularityStrategyTest::testDirectionExpand()
|
| +{
|
| + // Expand selection using character granularity until the end of the word
|
| + // is reached.
|
| + // "abcdef ghij kl mno^pq|>r stuvwi inm mnii,"
|
| + selection().moveRangeSelectionExtent(m_letterPos[20]);
|
| + EXPECT_EQ_SELECTED_TEXT("pq");
|
| + // Move to the same postion shouldn't change anything.
|
| + selection().moveRangeSelectionExtent(m_letterPos[20]);
|
| + EXPECT_EQ_SELECTED_TEXT("pq");
|
| + // "abcdef ghij kl mno^pqr|> stuvwi inm mnii,"
|
| + selection().moveRangeSelectionExtent(m_letterPos[21]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + // Selection should stay the same until the middle of the word is passed.
|
| + // "abcdef ghij kl mno^pqr |>stuvwi inm mnii," -
|
| + selection().moveRangeSelectionExtent(m_letterPos[22]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr ");
|
| + // "abcdef ghij kl mno^pqr >st|uvwi inm mnii,"
|
| + selection().moveRangeSelectionExtent(m_letterPos[24]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr ");
|
| + IntPoint p = m_wordMiddles[4];
|
| + p.move(-1, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr ");
|
| + p.move(1, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr stuvwi");
|
| + // Selection should stay the same until the end of the word is reached.
|
| + // "abcdef ghij kl mno^pqr stuvw|i> inm mnii,"
|
| + selection().moveRangeSelectionExtent(m_letterPos[27]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr stuvwi");
|
| + // "abcdef ghij kl mno^pqr stuvwi|> inm mnii,"
|
| + selection().moveRangeSelectionExtent(m_letterPos[28]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr stuvwi");
|
| + // "abcdef ghij kl mno^pqr stuvwi |>inm mnii,"
|
| + selection().moveRangeSelectionExtent(m_letterPos[29]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr stuvwi ");
|
| + // Now expand slowly to the middle of word #5.
|
| + int y = m_letterPos[29].y();
|
| + for (int x = m_letterPos[29].x() + 1; x < m_wordMiddles[5].x(); x++) {
|
| + selection().moveRangeSelectionExtent(IntPoint(x, y));
|
| + selection().moveRangeSelectionExtent(IntPoint(x, y));
|
| + EXPECT_EQ_SELECTED_TEXT("pqr stuvwi ");
|
| + }
|
| + selection().moveRangeSelectionExtent(m_wordMiddles[5]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr stuvwi inm");
|
| + // Jump over quickly to just before the middle of the word #6 and then
|
| + // move over it.
|
| + p = m_wordMiddles[6];
|
| + p.move(-1, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr stuvwi inm ");
|
| + p.move(1, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr stuvwi inm mnii");
|
| +}
|
| +
|
| +// Tests shrinking selection on text "abcdef ghij kl mno^pqr|> iiinmni, abc"
|
| +// (^ means base, | means extent, < means start, and > means end).
|
| +// Text needs to be laid out on a single line with no rotation.
|
| +void GranularityStrategyTest::testDirectionShrink()
|
| +{
|
| + // Move to the middle of word #4 to it and then move back, confirming
|
| + // that the selection end is moving with the extent. The offset between the
|
| + // extent and the selection end will be equal to half the width of "iiinmni".
|
| + selection().moveRangeSelectionExtent(m_wordMiddles[4]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iiinmni");
|
| + IntPoint p = m_wordMiddles[4];
|
| + p.move(m_letterPos[28].x() - m_letterPos[29].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iiinmn");
|
| + p.move(m_letterPos[27].x() - m_letterPos[28].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iiinm");
|
| + p.move(m_letterPos[26].x() - m_letterPos[27].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iiin");
|
| + // Move right by the width of char 30 ('m'). Selection shouldn't change,
|
| + // but offset should be reduced.
|
| + p.move(m_letterPos[27].x() - m_letterPos[26].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iiin");
|
| + // Move back a couple of character widths and confirm the selection still
|
| + // updates accordingly.
|
| + p.move(m_letterPos[25].x() - m_letterPos[26].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iii");
|
| + p.move(m_letterPos[24].x() - m_letterPos[25].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr ii");
|
| + // "Catch up" with the handle - move the extent to where the handle is.
|
| + // "abcdef ghij kl mno^pqr ii|>inmni, abc"
|
| + selection().moveRangeSelectionExtent(m_letterPos[24]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr ii");
|
| + // Move ahead and confirm the selection expands accordingly
|
| + // "abcdef ghij kl mno^pqr iii|>nmni, abc"
|
| + selection().moveRangeSelectionExtent(m_letterPos[25]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iii");
|
| +
|
| + // Confirm we stay in character granularity if the user moves within a word.
|
| + // "abcdef ghij kl mno^pqr |>iiinmni, abc"
|
| + selection().moveRangeSelectionExtent(m_letterPos[22]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr ");
|
| + // It's possible to get a move when position doesn't change.
|
| + // It shouldn't affect anything.
|
| + p = m_letterPos[22];
|
| + p.move(1, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr ");
|
| + // "abcdef ghij kl mno^pqr i|>iinmni, abc"
|
| + selection().moveRangeSelectionExtent(m_letterPos[23]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr i");
|
| +}
|
| +
|
| +// Tests moving selection extent over to the other side of the base
|
| +// on text "abcd efgh ijkl mno^pqr|> iiinmni, abc"
|
| +// (^ means base, | means extent, < means start, and > means end).
|
| +// Text needs to be laid out on a single line with no rotation.
|
| +void GranularityStrategyTest::testDirectionSwitchSide()
|
| +{
|
| + // Move to the middle of word #4, selecting it - this will set the offset to
|
| + // be half the width of "iiinmni.
|
| + selection().moveRangeSelectionExtent(m_wordMiddles[4]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iiinmni");
|
| + // Move back leaving only one letter selected.
|
| + IntPoint p = m_wordMiddles[4];
|
| + p.move(m_letterPos[19].x() - m_letterPos[29].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("p");
|
| + // Confirm selection doesn't change if extent is positioned at base.
|
| + p.move(m_letterPos[18].x() - m_letterPos[19].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("p");
|
| + // Move over to the other side of the base. Confirm the offset is preserved.
|
| + // (i.e. the selection start stays on the right of the extent)
|
| + // Confirm we stay in character granularity until the beginning of the word
|
| + // is passed.
|
| + p.move(m_letterPos[17].x() - m_letterPos[18].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("o");
|
| + p.move(m_letterPos[16].x() - m_letterPos[17].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("no");
|
| + p.move(m_letterPos[14].x() - m_letterPos[16].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT(" mno");
|
| + // Move to just one pixel on the right before the middle of the word #2.
|
| + // We should switch to word granularity, so the selection shouldn't change.
|
| + p.move(m_wordMiddles[2].x() - m_letterPos[14].x() + 1, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT(" mno");
|
| + // Move over the middle of the word. The word should get selected.
|
| + // This should reduce the offset, but it should still stay greated than 0,
|
| + // since the width of "iiinmni" is greater than the width of "ijkl".
|
| + p.move(-2, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("ijkl mno");
|
| + // Move to just one pixel on the right of the middle of word #1.
|
| + // The selection should now include the space between the words.
|
| + p.move(m_wordMiddles[1].x() - m_letterPos[10].x() + 1, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT(" ijkl mno");
|
| + // Move over the middle of the word. The word should get selected.
|
| + p.move(-2, 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("efgh ijkl mno");
|
| +}
|
| +
|
| +// Test for the default CharacterGranularityStrategy
|
| +TEST_F(GranularityStrategyTest, Character)
|
| +{
|
| + dummyPageHolder().frame().settings()->setSelectionStrategy(SelectionStrategy::Character);
|
| + dummyPageHolder().frame().settings()->setDefaultFontSize(12);
|
| + // "Foo Bar Baz,"
|
| + RefPtrWillBeRawPtr<Text> text = appendTextNode("Foo Bar Baz,");
|
| + // "Foo B^a|>r Baz," (^ means base, | means extent, , < means start, and > means end).
|
| + selection().setSelection(VisibleSelection(Position(text, 5), Position(text, 6)));
|
| + EXPECT_EQ_SELECTED_TEXT("a");
|
| + // "Foo B^ar B|>az,"
|
| + selection().moveRangeSelectionExtent(visiblePositionToContentsPoint(VisiblePosition(Position(text, 9))));
|
| + EXPECT_EQ_SELECTED_TEXT("ar B");
|
| + // "F<|oo B^ar Baz,"
|
| + selection().moveRangeSelectionExtent(visiblePositionToContentsPoint(VisiblePosition(Position(text, 1))));
|
| + EXPECT_EQ_SELECTED_TEXT("oo B");
|
| +}
|
| +
|
| +// DirectionGranularityStrategy strategy on rotated text should revert to the
|
| +// same behavior as CharacterGranularityStrategy
|
| +TEST_F(GranularityStrategyTest, DirectionRotate)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text = setupRotate("Foo Bar Baz,");
|
| + // "Foo B^a|>r Baz," (^ means base, | means extent, , < means start, and > means end).
|
| + selection().setSelection(VisibleSelection(Position(text, 5), Position(text, 6)));
|
| + EXPECT_EQ_SELECTED_TEXT("a");
|
| + IntPoint p = m_letterPos[9];
|
| + // Need to move by one pixel, otherwise this point is not evaluated
|
| + // to the same line as the text by hit testing.
|
| + p.move(1, 0);
|
| + // "Foo B^ar B|>az,"
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("ar B");
|
| + p = m_letterPos[1];
|
| + p.move(1, 0);
|
| + // "F<|oo B^ar Baz,"
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("oo B");
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionExpandTranslateZ)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text = setupTranslateZ("abcdef ghij kl mnopqr stuvwi inm mnii,");
|
| + // "abcdef ghij kl mno^p|>qr stuvwi inm mnii," (^ means base, | means extent, < means start, and > means end).
|
| + selection().setSelection(VisibleSelection(Position(text, 18), Position(text, 19)));
|
| + EXPECT_EQ_SELECTED_TEXT("p");
|
| + testDirectionExpand();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionExpandTransform)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text = setupTransform("abcdef ghij kl mnopqr stuvwi inm mnii,");
|
| + // "abcdef ghij kl mno^p|>qr stuvwi inm mnii," (^ means base, | means extent, < means start, and > means end).
|
| + selection().setSelection(VisibleSelection(Position(text, 18), Position(text, 19)));
|
| + EXPECT_EQ_SELECTED_TEXT("p");
|
| + testDirectionExpand();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionExpandVerticalAlign)
|
| +{
|
| + // "abcdef ghij kl mno^p|>qr stuvwi inm mnii," (^ means base, | means extent, < means start, and > means end).
|
| + setupVerticalAlign("abcdef ghij kl m", "nopq", "r stuvwi inm mnii,", 18, 19);
|
| + EXPECT_EQ_SELECTED_TEXT("p");
|
| + testDirectionExpand();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionExpandFontSizes)
|
| +{
|
| + setupFontSize("abcdef ghij kl mnopqr st", "uv", "wi inm mnii,", 18, 19);
|
| + EXPECT_EQ_SELECTED_TEXT("p");
|
| + testDirectionExpand();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionShrinkTranslateZ)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text = setupTranslateZ("abcdef ghij kl mnopqr iiinmni, abc");
|
| + selection().setSelection(VisibleSelection(Position(text, 18), Position(text, 21)));
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + testDirectionShrink();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionShrinkTransform)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text = setupTransform("abcdef ghij kl mnopqr iiinmni, abc");
|
| + selection().setSelection(VisibleSelection(Position(text, 18), Position(text, 21)));
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + testDirectionShrink();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionShrinkVerticalAlign)
|
| +{
|
| + setupVerticalAlign("abcdef ghij kl mnopqr ii", "inm", "ni, abc", 18, 21);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + testDirectionShrink();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionShrinkFontSizes)
|
| +{
|
| + setupFontSize("abcdef ghij kl mnopqr ii", "inm", "ni, abc", 18, 21);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + testDirectionShrink();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionSwitchSideTranslateZ)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text = setupTranslateZ("abcd efgh ijkl mnopqr iiinmni, abc");
|
| + selection().setSelection(VisibleSelection(Position(text, 18), Position(text, 21)));
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + testDirectionSwitchSide();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionSwitchSideTransform)
|
| +{
|
| + RefPtrWillBeRawPtr<Text> text = setupTransform("abcd efgh ijkl mnopqr iiinmni, abc");
|
| + selection().setSelection(VisibleSelection(Position(text, 18), Position(text, 21)));
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + testDirectionSwitchSide();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionSwitchSideVerticalAlign)
|
| +{
|
| + setupVerticalAlign("abcd efgh ijkl", " mnopqr", " iiinmni, abc", 18, 21);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + testDirectionSwitchSide();
|
| +}
|
| +
|
| +TEST_F(GranularityStrategyTest, DirectionSwitchSideFontSizes)
|
| +{
|
| + setupFontSize("abcd efgh i", "jk", "l mnopqr iiinmni, abc", 18, 21);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + testDirectionSwitchSide();
|
| +}
|
| +
|
| +// Tests moving extent over to the other side of the vase and immediately
|
| +// passing the word boundary and going into word granularity.
|
| +TEST_F(GranularityStrategyTest, DirectionSwitchSideWordGranularityThenShrink)
|
| +{
|
| + dummyPageHolder().frame().settings()->setDefaultFontSize(12);
|
| + WTF::String str = "ab cd efghijkl mnopqr iiin, abc";
|
| + RefPtrWillBeRawPtr<Text> text = document().createTextNode(str);
|
| + document().body()->appendChild(text);
|
| + dummyPageHolder().frame().settings()->setSelectionStrategy(SelectionStrategy::Direction);
|
| +
|
| + parseText(text.get());
|
| +
|
| + // "abcd efgh ijkl mno^pqr|> iiin, abc" (^ means base, | means extent, < means start, and > means end).
|
| + selection().setSelection(VisibleSelection(Position(text, 18), Position(text, 21)));
|
| + EXPECT_EQ_SELECTED_TEXT("pqr");
|
| + // Move to the middle of word #4 selecting it - this will set the offset to
|
| + // be half the width of "iiin".
|
| + selection().moveRangeSelectionExtent(m_wordMiddles[4]);
|
| + EXPECT_EQ_SELECTED_TEXT("pqr iiin");
|
| + // Move to the middle of word #2 - extent will switch over to the other
|
| + // side of the base, and we should enter word granularity since we pass
|
| + // the word boundary. The offset should become negative since the width
|
| + // of "efghjkkl" is greater than that of "iiin".
|
| + int offset = m_letterPos[26].x() - m_wordMiddles[4].x();
|
| + IntPoint p = IntPoint(m_wordMiddles[2].x() - offset - 1, m_wordMiddles[2].y());
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("efghijkl mno");
|
| + p.move(m_letterPos[7].x() - m_letterPos[6].x(), 0);
|
| + selection().moveRangeSelectionExtent(p);
|
| + EXPECT_EQ_SELECTED_TEXT("fghijkl mno");
|
| +}
|
| +
|
| +// Make sure we switch to word granularity right away when starting on a
|
| +// word boundary and extending.
|
| +TEST_F(GranularityStrategyTest, DirectionSwitchStartOnBoundary)
|
| +{
|
| + dummyPageHolder().frame().settings()->setDefaultFontSize(12);
|
| + WTF::String str = "ab cd efghijkl mnopqr iiin, abc";
|
| + RefPtrWillBeRawPtr<Text> text = document().createTextNode(str);
|
| + document().body()->appendChild(text);
|
| + dummyPageHolder().frame().settings()->setSelectionStrategy(SelectionStrategy::Direction);
|
| +
|
| + parseText(text.get());
|
| +
|
| + // "ab cd efghijkl ^mnopqr |>stuvwi inm," (^ means base and | means extent,
|
| + // > means end).
|
| + selection().setSelection(VisibleSelection(Position(text, 15), Position(text, 22)));
|
| + EXPECT_EQ_SELECTED_TEXT("mnopqr ");
|
| + selection().moveRangeSelectionExtent(m_wordMiddles[4]);
|
| + EXPECT_EQ_SELECTED_TEXT("mnopqr iiin");
|
| +}
|
| +}
|
|
|