| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/editing/VisibleSelection.h" | 6 #include "core/editing/VisibleSelection.h" |
| 7 | 7 |
| 8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
| 9 #include "core/dom/Range.h" | 9 #include "core/dom/Range.h" |
| 10 #include "core/dom/Text.h" | 10 #include "core/dom/Text.h" |
| 11 #include "core/html/HTMLElement.h" | 11 #include "core/html/HTMLElement.h" |
| 12 #include "core/testing/CoreTestHelpers.h" | |
| 13 #include "core/testing/DummyPageHolder.h" | 12 #include "core/testing/DummyPageHolder.h" |
| 14 #include <gtest/gtest.h> | 13 #include <gtest/gtest.h> |
| 15 | 14 |
| 16 #define LOREM_IPSUM \ | 15 #define LOREM_IPSUM \ |
| 17 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod te
mpor " \ | 16 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod te
mpor " \ |
| 18 "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud " \ | 17 "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud " \ |
| 19 "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure " \ | 18 "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure " \ |
| 20 "dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat null
a pariatur." \ | 19 "dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat null
a pariatur." \ |
| 21 "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia d
eserunt " \ | 20 "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia d
eserunt " \ |
| 22 "mollit anim id est laborum." | 21 "mollit anim id est laborum." |
| 23 | 22 |
| 24 namespace blink { | 23 namespace blink { |
| 25 | 24 |
| 26 class VisibleSelectionTest : public ::testing::Test { | 25 class VisibleSelectionTest : public ::testing::Test { |
| 27 protected: | 26 protected: |
| 28 virtual void SetUp() override; | 27 virtual void SetUp() override; |
| 29 | 28 |
| 29 // Oilpan: wrapper object needed to be able to trace VisibleSelection. |
| 30 class VisibleSelectionWrapper : public NoBaseWillBeGarbageCollectedFinalized
<VisibleSelectionWrapper> { |
| 31 public: |
| 32 DEFINE_INLINE_TRACE() |
| 33 { |
| 34 visitor->trace(m_selection); |
| 35 } |
| 36 |
| 37 VisibleSelection m_selection; |
| 38 }; |
| 39 |
| 30 Document& document() const { return m_dummyPageHolder->document(); } | 40 Document& document() const { return m_dummyPageHolder->document(); } |
| 31 | 41 Text* textNode() const { return m_textNode.get(); } |
| 32 static PassRefPtrWillBeRawPtr<ShadowRoot> createShadowRootForElementWithIDAn
dSetInnerHTML(TreeScope&, const char* hostElementID, const char* shadowRootConte
nt); | 42 VisibleSelection& selection() { return m_wrap->m_selection; } |
| 33 | |
| 34 void setBodyContent(const char*); | |
| 35 PassRefPtrWillBeRawPtr<ShadowRoot> setShadowContent(const char*); | |
| 36 | 43 |
| 37 // Helper function to set the VisibleSelection base/extent. | 44 // Helper function to set the VisibleSelection base/extent. |
| 38 void setSelection(VisibleSelection& selection, int base) { setSelection(sele
ction, base, base); } | 45 void setSelection(int base) { setSelection(base, base); } |
| 39 | 46 |
| 40 // Helper function to set the VisibleSelection base/extent. | 47 // Helper function to set the VisibleSelection base/extent. |
| 41 void setSelection(VisibleSelection& selection, int base, int extend) | 48 void setSelection(int base, int extend) |
| 42 { | 49 { |
| 43 Node* node = document().body()->firstChild(); | 50 m_wrap->m_selection.setBase(Position(textNode(), base)); |
| 44 selection.setBase(Position(node, base, Position::PositionIsOffsetInAncho
r)); | 51 m_wrap->m_selection.setExtent(Position(textNode(), extend)); |
| 45 selection.setExtent(Position(node, extend, Position::PositionIsOffsetInA
nchor)); | |
| 46 } | 52 } |
| 47 | 53 |
| 48 private: | 54 private: |
| 49 OwnPtr<DummyPageHolder> m_dummyPageHolder; | 55 OwnPtr<DummyPageHolder> m_dummyPageHolder; |
| 56 RefPtrWillBePersistent<Text> m_textNode; |
| 57 OwnPtrWillBePersistent<VisibleSelectionWrapper> m_wrap; |
| 50 }; | 58 }; |
| 51 | 59 |
| 52 void VisibleSelectionTest::SetUp() | 60 void blink::VisibleSelectionTest::SetUp() |
| 53 { | 61 { |
| 54 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); | 62 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); |
| 63 m_textNode = document().createTextNode(LOREM_IPSUM); |
| 64 m_wrap = adoptPtrWillBeNoop(new VisibleSelectionWrapper()); |
| 65 document().body()->appendChild(m_textNode.get()); |
| 55 } | 66 } |
| 56 | 67 |
| 57 PassRefPtrWillBeRawPtr<ShadowRoot> VisibleSelectionTest::createShadowRootForElem
entWithIDAndSetInnerHTML(TreeScope& scope, const char* hostElementID, const char
* shadowRootContent) | 68 } // namespace blink |
| 58 { | |
| 59 RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = scope.getElementById(AtomicStrin
g::fromUTF8(hostElementID))->createShadowRoot(ASSERT_NO_EXCEPTION); | |
| 60 shadowRoot->setInnerHTML(String::fromUTF8(shadowRootContent), ASSERT_NO_EXCE
PTION); | |
| 61 return shadowRoot.release(); | |
| 62 } | |
| 63 | 69 |
| 64 void VisibleSelectionTest::setBodyContent(const char* bodyContent) | 70 namespace { |
| 65 { | |
| 66 document().body()->setInnerHTML(String::fromUTF8(bodyContent), ASSERT_NO_EXC
EPTION); | |
| 67 } | |
| 68 | 71 |
| 69 PassRefPtrWillBeRawPtr<ShadowRoot> VisibleSelectionTest::setShadowContent(const
char* shadowContent) | 72 using namespace blink; |
| 70 { | |
| 71 return createShadowRootForElementWithIDAndSetInnerHTML(document(), "host", s
hadowContent); | |
| 72 } | |
| 73 | 73 |
| 74 TEST_F(VisibleSelectionTest, Initialisation) | 74 TEST_F(VisibleSelectionTest, Initialisation) |
| 75 { | 75 { |
| 76 setBodyContent(LOREM_IPSUM); | 76 setSelection(0); |
| 77 | 77 |
| 78 VisibleSelection selection; | 78 EXPECT_FALSE(selection().isNone()); |
| 79 setSelection(selection, 0); | 79 EXPECT_TRUE(selection().isCaret()); |
| 80 | 80 |
| 81 EXPECT_FALSE(selection.isNone()); | 81 RefPtrWillBeRawPtr<Range> range = selection().firstRange(); |
| 82 EXPECT_TRUE(selection.isCaret()); | |
| 83 | |
| 84 RefPtrWillBeRawPtr<Range> range = selection.firstRange(); | |
| 85 EXPECT_EQ(0, range->startOffset()); | 82 EXPECT_EQ(0, range->startOffset()); |
| 86 EXPECT_EQ(0, range->endOffset()); | 83 EXPECT_EQ(0, range->endOffset()); |
| 87 EXPECT_EQ("", range->text()); | 84 EXPECT_EQ("", range->text()); |
| 88 } | 85 } |
| 89 | 86 |
| 90 TEST_F(VisibleSelectionTest, ShadowCrossing) | |
| 91 { | |
| 92 static const char* bodyContent = "<p id='host'>00<b id='one'>11</b><b id='tw
o'>22</b>33</p>"; | |
| 93 static const char* shadowContent = "<a><span id='s4'>44</span><content selec
t=#two></content><span id='s5'>55</span><content select=#one></content><span id=
's6'>66</span></a>"; | |
| 94 setBodyContent(bodyContent); | |
| 95 RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent); | |
| 96 | |
| 97 RefPtrWillBeRawPtr<Element> body = document().body(); | |
| 98 RefPtrWillBeRawPtr<Element> host = body->querySelector("#host", ASSERT_NO_EX
CEPTION); | |
| 99 RefPtrWillBeRawPtr<Element> one = body->querySelector("#one", ASSERT_NO_EXCE
PTION); | |
| 100 RefPtrWillBeRawPtr<Element> two = body->querySelector("#two", ASSERT_NO_EXCE
PTION); | |
| 101 RefPtrWillBeRawPtr<Element> six = shadowRoot->querySelector("#s6", ASSERT_NO
_EXCEPTION); | |
| 102 | |
| 103 VisibleSelection selection(Position::firstPositionInNode(one.get()), Positio
n::lastPositionInNode(shadowRoot.get())); | |
| 104 | |
| 105 EXPECT_EQ(Position(host.get(), Position::PositionIsBeforeAnchor), selection.
start()); | |
| 106 EXPECT_EQ(Position(one->firstChild(), 0, Position::PositionIsOffsetInAnchor)
, selection.end()); | |
| 107 } | |
| 108 | |
| 109 TEST_F(VisibleSelectionTest, ShadowDistributedNodes) | |
| 110 { | |
| 111 static const char* bodyContent = "<p id='host'>00<b id='one'>11</b><b id='tw
o'>22</b>33</p>"; | |
| 112 static const char* shadowContent = "<a><span id='s4'>44</span><content selec
t=#two></content><span id='s5'>55</span><content select=#one></content><span id=
's6'>66</span></a>"; | |
| 113 setBodyContent(bodyContent); | |
| 114 RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent); | |
| 115 | |
| 116 RefPtrWillBeRawPtr<Element> body = document().body(); | |
| 117 RefPtrWillBeRawPtr<Element> host = body->querySelector("#host", ASSERT_NO_EX
CEPTION); | |
| 118 RefPtrWillBeRawPtr<Element> one = body->querySelector("#one", ASSERT_NO_EXCE
PTION); | |
| 119 RefPtrWillBeRawPtr<Element> two = body->querySelector("#two", ASSERT_NO_EXCE
PTION); | |
| 120 RefPtrWillBeRawPtr<Element> five = shadowRoot->querySelector("#s5", ASSERT_N
O_EXCEPTION); | |
| 121 | |
| 122 VisibleSelection selection(Position::firstPositionInNode(one.get()), Positio
n::lastPositionInNode(two.get())); | |
| 123 | |
| 124 EXPECT_EQ(Position(one->firstChild(), 0, Position::PositionIsOffsetInAnchor)
, selection.start()); | |
| 125 EXPECT_EQ(Position(two->firstChild(), 2, Position::PositionIsOffsetInAnchor)
, selection.end()); | |
| 126 } | |
| 127 | |
| 128 TEST_F(VisibleSelectionTest, ShadowNested) | |
| 129 { | |
| 130 static const char* bodyContent = "<p id='host'>00<b id='one'>11</b><b id='tw
o'>22</b>33</p>"; | |
| 131 static const char* shadowContent = "<a><span id='s4'>44</span><content selec
t=#two></content><span id='s5'>55</span><content select=#one></content><span id=
's6'>66</span></a>"; | |
| 132 static const char* shadowContent2 = "<span id='s7'>77</span><content></conte
nt><span id='s8'>88</span>"; | |
| 133 setBodyContent(bodyContent); | |
| 134 RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent); | |
| 135 RefPtrWillBeRawPtr<ShadowRoot> shadowRoot2 = createShadowRootForElementWithI
DAndSetInnerHTML(*shadowRoot, "s5", shadowContent2); | |
| 136 | |
| 137 RefPtrWillBeRawPtr<Element> body = document().body(); | |
| 138 RefPtrWillBeRawPtr<Element> host = body->querySelector("#host", ASSERT_NO_EX
CEPTION); | |
| 139 RefPtrWillBeRawPtr<Element> one = body->querySelector("#one", ASSERT_NO_EXCE
PTION); | |
| 140 RefPtrWillBeRawPtr<Element> two = body->querySelector("#two", ASSERT_NO_EXCE
PTION); | |
| 141 RefPtrWillBeRawPtr<Element> host2 = shadowRoot->querySelector("#host2", ASSE
RT_NO_EXCEPTION); | |
| 142 RefPtrWillBeRawPtr<Element> eight = shadowRoot2->querySelector("#s8", ASSERT
_NO_EXCEPTION); | |
| 143 | |
| 144 VisibleSelection selection(Position::firstPositionInNode(one.get()), Positio
n::lastPositionInNode(shadowRoot2.get())); | |
| 145 | |
| 146 EXPECT_EQ(Position(host.get(), Position::PositionIsBeforeAnchor), selection.
start()); | |
| 147 EXPECT_EQ(Position(one->firstChild(), 0, Position::PositionIsOffsetInAnchor)
, selection.end()); | |
| 148 } | |
| 149 | |
| 150 TEST_F(VisibleSelectionTest, WordGranularity) | 87 TEST_F(VisibleSelectionTest, WordGranularity) |
| 151 { | 88 { |
| 152 setBodyContent(LOREM_IPSUM); | |
| 153 | |
| 154 VisibleSelection selection; | |
| 155 | |
| 156 // Beginning of a word. | 89 // Beginning of a word. |
| 157 { | 90 { |
| 158 setSelection(selection, 0); | 91 setSelection(0); |
| 159 selection.expandUsingGranularity(WordGranularity); | 92 selection().expandUsingGranularity(WordGranularity); |
| 160 | 93 |
| 161 RefPtrWillBeRawPtr<Range> range = selection.firstRange(); | 94 RefPtrWillBeRawPtr<Range> range = selection().firstRange(); |
| 162 EXPECT_EQ(0, range->startOffset()); | 95 EXPECT_EQ(0, range->startOffset()); |
| 163 EXPECT_EQ(5, range->endOffset()); | 96 EXPECT_EQ(5, range->endOffset()); |
| 164 EXPECT_EQ("Lorem", range->text()); | 97 EXPECT_EQ("Lorem", range->text()); |
| 165 } | 98 } |
| 166 | 99 |
| 167 // Middle of a word. | 100 // Middle of a word. |
| 168 { | 101 { |
| 169 setSelection(selection, 8); | 102 setSelection(8); |
| 170 selection.expandUsingGranularity(WordGranularity); | 103 selection().expandUsingGranularity(WordGranularity); |
| 171 | 104 |
| 172 RefPtrWillBeRawPtr<Range> range = selection.firstRange(); | 105 RefPtrWillBeRawPtr<Range> range = selection().firstRange(); |
| 173 EXPECT_EQ(6, range->startOffset()); | 106 EXPECT_EQ(6, range->startOffset()); |
| 174 EXPECT_EQ(11, range->endOffset()); | 107 EXPECT_EQ(11, range->endOffset()); |
| 175 EXPECT_EQ("ipsum", range->text()); | 108 EXPECT_EQ("ipsum", range->text()); |
| 176 } | 109 } |
| 177 | 110 |
| 178 // End of a word. | 111 // End of a word. |
| 179 // FIXME: that sounds buggy, we might want to select the word _before_ inste
ad | 112 // FIXME: that sounds buggy, we might want to select the word _before_ inste
ad |
| 180 // of the space... | 113 // of the space... |
| 181 { | 114 { |
| 182 setSelection(selection, 5); | 115 setSelection(5); |
| 183 selection.expandUsingGranularity(WordGranularity); | 116 selection().expandUsingGranularity(WordGranularity); |
| 184 | 117 |
| 185 RefPtrWillBeRawPtr<Range> range = selection.firstRange(); | 118 RefPtrWillBeRawPtr<Range> range = selection().firstRange(); |
| 186 EXPECT_EQ(5, range->startOffset()); | 119 EXPECT_EQ(5, range->startOffset()); |
| 187 EXPECT_EQ(6, range->endOffset()); | 120 EXPECT_EQ(6, range->endOffset()); |
| 188 EXPECT_EQ(" ", range->text()); | 121 EXPECT_EQ(" ", range->text()); |
| 189 } | 122 } |
| 190 | 123 |
| 191 // Before comma. | 124 // Before comma. |
| 192 // FIXME: that sounds buggy, we might want to select the word _before_ inste
ad | 125 // FIXME: that sounds buggy, we might want to select the word _before_ inste
ad |
| 193 // of the comma. | 126 // of the comma. |
| 194 { | 127 { |
| 195 setSelection(selection, 26); | 128 setSelection(26); |
| 196 selection.expandUsingGranularity(WordGranularity); | 129 selection().expandUsingGranularity(WordGranularity); |
| 197 | 130 |
| 198 RefPtrWillBeRawPtr<Range> range = selection.firstRange(); | 131 RefPtrWillBeRawPtr<Range> range = selection().firstRange(); |
| 199 EXPECT_EQ(26, range->startOffset()); | 132 EXPECT_EQ(26, range->startOffset()); |
| 200 EXPECT_EQ(27, range->endOffset()); | 133 EXPECT_EQ(27, range->endOffset()); |
| 201 EXPECT_EQ(",", range->text()); | 134 EXPECT_EQ(",", range->text()); |
| 202 } | 135 } |
| 203 | 136 |
| 204 // After comma. | 137 // After comma. |
| 205 { | 138 { |
| 206 setSelection(selection, 27); | 139 setSelection(27); |
| 207 selection.expandUsingGranularity(WordGranularity); | 140 selection().expandUsingGranularity(WordGranularity); |
| 208 | 141 |
| 209 RefPtrWillBeRawPtr<Range> range = selection.firstRange(); | 142 RefPtrWillBeRawPtr<Range> range = selection().firstRange(); |
| 210 EXPECT_EQ(27, range->startOffset()); | 143 EXPECT_EQ(27, range->startOffset()); |
| 211 EXPECT_EQ(28, range->endOffset()); | 144 EXPECT_EQ(28, range->endOffset()); |
| 212 EXPECT_EQ(" ", range->text()); | 145 EXPECT_EQ(" ", range->text()); |
| 213 } | 146 } |
| 214 | 147 |
| 215 // When selecting part of a word. | 148 // When selecting part of a word. |
| 216 { | 149 { |
| 217 setSelection(selection, 0, 1); | 150 setSelection(0, 1); |
| 218 selection.expandUsingGranularity(WordGranularity); | 151 selection().expandUsingGranularity(WordGranularity); |
| 219 | 152 |
| 220 RefPtrWillBeRawPtr<Range> range = selection.firstRange(); | 153 RefPtrWillBeRawPtr<Range> range = selection().firstRange(); |
| 221 EXPECT_EQ(0, range->startOffset()); | 154 EXPECT_EQ(0, range->startOffset()); |
| 222 EXPECT_EQ(5, range->endOffset()); | 155 EXPECT_EQ(5, range->endOffset()); |
| 223 EXPECT_EQ("Lorem", range->text()); | 156 EXPECT_EQ("Lorem", range->text()); |
| 224 } | 157 } |
| 225 | 158 |
| 226 // When selecting part of two words. | 159 // When selecting part of two words. |
| 227 { | 160 { |
| 228 setSelection(selection, 2, 8); | 161 setSelection(2, 8); |
| 229 selection.expandUsingGranularity(WordGranularity); | 162 selection().expandUsingGranularity(WordGranularity); |
| 230 | 163 |
| 231 RefPtrWillBeRawPtr<Range> range = selection.firstRange(); | 164 RefPtrWillBeRawPtr<Range> range = selection().firstRange(); |
| 232 EXPECT_EQ(0, range->startOffset()); | 165 EXPECT_EQ(0, range->startOffset()); |
| 233 EXPECT_EQ(11, range->endOffset()); | 166 EXPECT_EQ(11, range->endOffset()); |
| 234 EXPECT_EQ("Lorem ipsum", range->text()); | 167 EXPECT_EQ("Lorem ipsum", range->text()); |
| 235 } | 168 } |
| 236 } | 169 } |
| 237 | 170 |
| 238 } // namespace blink | 171 } // namespace blink |
| OLD | NEW |