Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(655)

Side by Side Diff: third_party/WebKit/Source/web/tests/LinkSelectionTest.cpp

Issue 1774123006: Implement link selection on alt+mouse drag. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/dom/Range.h"
6 #include "core/frame/FrameView.h"
7 #include "core/input/EventHandler.h"
8 #include "core/page/ChromeClient.h"
9 #include "core/page/ContextMenuController.h"
10 #include "core/page/FocusController.h"
11 #include "core/page/Page.h"
12 #include "platform/Cursor.h"
13 #include "platform/testing/URLTestHelpers.h"
14 #include "platform/testing/UnitTestHelpers.h"
15 #include "public/web/WebSettings.h"
16 #include "web/WebLocalFrameImpl.h"
17 #include "web/tests/SelectionTestBase.h"
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 using ::testing::_;
23
24 namespace blink {
25 namespace {
yosin_UTC9 2016/03/10 01:40:48 Note: We don't need to enclose test fixture class
26 class TestFrameClient : public FrameTestHelpers::TestWebFrameClient {
27 public:
28 MOCK_METHOD4(loadURLExternally,
29 void(const WebURLRequest&, WebNavigationPolicy, const WebString& downloa dName, bool shouldReplaceCurrentEntry));
30 };
31
32 class LinkSelectionTest : public SelectionTestBase {
33 protected:
34 void SetUp() override
35 {
36 static const char* kHTMLString =
37 "<a id='link' href='foo.com' style='font-size:20pt'>Text to select f oobar</a>"
38 "<div id='page_text'>Lorem ipsum dolor sit amet</div>";
39
40 // We need to set deviceSupportsMouse setting to true and page's focus c ontroller to active
41 // so that FrameView can set the mouse cursor.
42 m_webView = m_helper.initialize(false, &m_testFrameClient, nullptr,
43 [](WebSettings* settings) { settings->setDeviceSupportsMouse(true); });
44 m_mainFrame = m_webView->mainFrameImpl();
45 FrameTestHelpers::loadHTMLString(m_mainFrame, kHTMLString, URLTestHelper s::toKURL("http://foobar.com"));
46 m_webView->resize(WebSize(800, 600));
47 m_webView->page()->focusController().setActive(true);
48
49 auto* document = m_mainFrame->frame()->document();
50 ASSERT(document);
51 auto* linkToSelect = document->getElementById("link")->firstChild();
52 ASSERT(linkToSelect);
53 // We get larger range that we actually want to select, because we need a slightly larger
54 // rect to include the last character to the selection.
55 const auto rangeToSelect = Range::create(*document, linkToSelect, 5, lin kToSelect, 16);
56
57 const auto& selectionRect = rangeToSelect->boundingBox();
58 const auto& selectionRectCenterY = selectionRect.center().y();
59 m_leftPointInLink = selectionRect.minXMinYCorner();
60 m_leftPointInLink.setY(selectionRectCenterY);
61
62 m_rightPointInLink = selectionRect.maxXMinYCorner();
63 m_rightPointInLink.setY(selectionRectCenterY);
64 m_rightPointInLink.move(-2, 0);
65 }
66
67 TestFrameClient m_testFrameClient;
68 IntPoint m_leftPointInLink;
69 IntPoint m_rightPointInLink;
70 };
71
72 TEST_F(LinkSelectionTest, MouseDragWithoutAltAllowNoLinkSelection)
73 {
74 emulateMouseDrag(m_leftPointInLink, m_rightPointInLink, 0);
75 EXPECT_EQ(std::string(), getSelectionText());
76 }
77
78 TEST_F(LinkSelectionTest, MouseDragWithAltAllowSelection)
79 {
80 emulateMouseDrag(m_leftPointInLink, m_rightPointInLink, WebInputEvent::AltKe y);
81 EXPECT_EQ("to select", getSelectionText());
82 }
83
84 TEST_F(LinkSelectionTest, HandCursorDuringLinkDrag)
85 {
86 emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, 0,
87 true /* sendDownEvent */, false /* sendUpEvent */);
yosin_UTC9 2016/03/10 01:40:48 How about writing this as: const bool sendDownEve
88 m_mainFrame->frame()->localFrameRoot()->eventHandler().scheduleCursorUpdate( );
89 testing::waitForDeferredTasks(0.05);
90 const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTe sting();
91 EXPECT_EQ(Cursor::Hand, cursor.getType());
92 }
93
94 TEST_F(LinkSelectionTest, CaretCursorOverLinkDuringSelection)
95 {
96 emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, WebInputEvent::AltKe y,
97 true /* sendDownEvent */, false /* sendUpEvent */);
98 m_mainFrame->frame()->localFrameRoot()->eventHandler().scheduleCursorUpdate( );
99 testing::waitForDeferredTasks(0.05);
100 const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTe sting();
101 EXPECT_EQ(Cursor::IBeam, cursor.getType());
102 }
103
104 TEST_F(LinkSelectionTest, HandCursorOverLinkAfterContextMenu)
105 {
106 // Move mouse.
107 emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, 0,
108 false /* sendDownEvent */, false /* sendUpEvent */);
109
110 // Show context menu. We don't send mouseup event here since in browser it d oesn't reach
111 // blink because of shown context menu.
112 emulateMouseDown(m_leftPointInLink, WebMouseEvent::ButtonRight, 0, 1);
113
114 LocalFrame* frame = m_mainFrame->frame();
115 // Hide context menu.
116 frame->page()->contextMenuController().clearContextMenu();
117
118 frame->localFrameRoot()->eventHandler().scheduleCursorUpdate();
119 testing::waitForDeferredTasks(0.05);
120 const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTe sting();
121 EXPECT_EQ(Cursor::Hand, cursor.getType());
122 }
123
124 TEST_F(LinkSelectionTest, SingleClickWithAltStartsDownload)
125 {
126 EXPECT_CALL(m_testFrameClient, loadURLExternally(_, WebNavigationPolicy::Web NavigationPolicyDownload, WebString(), _));
127 emulateMouseClick(m_leftPointInLink, WebMouseEvent::ButtonLeft, WebInputEven t::AltKey);
128 }
129
130 TEST_F(LinkSelectionTest, SingleClickWithAltStartsDownloadWhenTextSelected)
131 {
132 auto* document = m_mainFrame->frame()->document();
133 auto* textToSelect = document->getElementById("page_text")->firstChild();
134 ASSERT(textToSelect);
135
136 // Select some page text outside the link element.
137 const RefPtrWillBeRawPtr<Range> rangeToSelect = Range::create(*document, tex tToSelect, 1, textToSelect, 20);
138 const auto& selectionRect = rangeToSelect->boundingBox();
139 m_mainFrame->moveRangeSelection(selectionRect.minXMinYCorner(), selectionRec t.maxXMaxYCorner());
140 EXPECT_FALSE(getSelectionText().empty());
141
142 EXPECT_CALL(m_testFrameClient, loadURLExternally(_, WebNavigationPolicy::Web NavigationPolicyDownload, WebString(), _));
143 emulateMouseClick(m_leftPointInLink, WebMouseEvent::ButtonLeft, WebInputEven t::AltKey);
144 }
145
146 class ClickEventsBugTest : public SelectionTestBase {
147 protected:
148 class MockEventListener final : public EventListener {
149 public:
150 static PassRefPtrWillBeRawPtr<MockEventListener> create()
151 {
152 return adoptRefWillBeNoop(new MockEventListener());
153 }
154
155 bool operator==(const EventListener& other) const final
156 {
157 return this == &other;
158 }
159
160 MOCK_METHOD2(handleEvent, void(ExecutionContext* executionContext, Event *));
161
162 private:
163 MockEventListener() : EventListener(CPPEventListenerType)
164 {
165 }
166 };
167
168 void SetUp() override
169 {
170 static const char* kHTMLString =
171 "<div id='empty_div' style='width: 100px; height: 100px;'></div>"
172 "<span id='text_div'>Sometexttoshow</span>";
173
174 m_webView = m_helper.initialize(false);
175 m_mainFrame = m_webView->mainFrameImpl();
176 FrameTestHelpers::loadHTMLString(m_mainFrame, kHTMLString, URLTestHelper s::toKURL("http://foobar.com"));
177 m_webView->resize(WebSize(800, 600));
178 m_webView->page()->focusController().setActive(true);
179
180 auto* document = m_mainFrame->frame()->document();
181 ASSERT(document);
182
183 auto* emptyDiv = document->getElementById("empty_div");
184 auto* textDiv = document->getElementById("text_div");
185 ASSERT_TRUE(emptyDiv);
186 ASSERT_TRUE(textDiv);
187 }
188
189 void checkMouseClicks(Element& element, bool doubleClickEvent)
190 {
191 struct ScopedListenersCleaner {
192 ScopedListenersCleaner(Element* element) : m_element(element) {}
193
194 ~ScopedListenersCleaner()
195 {
196 m_element->removeAllEventListeners();
197 }
198
199 RawPtrWillBePersistent<Element> m_element;
200 } const listenersCleaner(&element);
201
202 RefPtrWillBeRawPtr<MockEventListener> eventHandler = MockEventListener:: create();
203 element.addEventListener(
204 doubleClickEvent ? EventTypeNames::dblclick : EventTypeNames::click,
205 eventHandler);
206
207 ::testing::InSequence s;
208 EXPECT_CALL(*eventHandler, handleEvent(_, _)).Times(1);
209
210 const auto& elemBounds = element.boundsInViewport();
211 const int clickCount = doubleClickEvent ? 2 : 1;
212 emulateMouseClick(elemBounds.center(), WebMouseEvent::ButtonLeft, 0, cli ckCount);
213
214 if (doubleClickEvent) {
215 EXPECT_EQ(element.innerText().isEmpty(), getSelectionText().empty()) ;
216 }
217 }
218 };
219
220 TEST_F(ClickEventsBugTest, SingleAndDoubleClickWillBeHandled)
221 {
222 auto* document = m_mainFrame->frame()->document();
223 auto* element = document->getElementById("empty_div");
224
225 {
226 SCOPED_TRACE("Empty div, single click");
227 checkMouseClicks(*element, false);
228 }
229
230 {
231 SCOPED_TRACE("Empty div, double click");
232 checkMouseClicks(*element, true);
233 }
234
235 element = document->getElementById("text_div");
236
237 {
238 SCOPED_TRACE("Text div, single click");
239 checkMouseClicks(*element, false);
240 }
241
242 {
243 SCOPED_TRACE("Text div, double click");
244 checkMouseClicks(*element, true);
245 }
246 }
247 } // namespace
248 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698