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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/web/tests/LinkSelectionTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/LinkSelectionTest.cpp b/third_party/WebKit/Source/web/tests/LinkSelectionTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d66da8a1f7852d10a33f0c84279bb057c502663
--- /dev/null
+++ b/third_party/WebKit/Source/web/tests/LinkSelectionTest.cpp
@@ -0,0 +1,248 @@
+// Copyright (c) 2016 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 "core/dom/Range.h"
+#include "core/frame/FrameView.h"
+#include "core/input/EventHandler.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/ContextMenuController.h"
+#include "core/page/FocusController.h"
+#include "core/page/Page.h"
+#include "platform/Cursor.h"
+#include "platform/testing/URLTestHelpers.h"
+#include "platform/testing/UnitTestHelpers.h"
+#include "public/web/WebSettings.h"
+#include "web/WebLocalFrameImpl.h"
+#include "web/tests/SelectionTestBase.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::_;
+
+namespace blink {
+namespace {
yosin_UTC9 2016/03/10 01:40:48 Note: We don't need to enclose test fixture class
+class TestFrameClient : public FrameTestHelpers::TestWebFrameClient {
+public:
+ MOCK_METHOD4(loadURLExternally,
+ void(const WebURLRequest&, WebNavigationPolicy, const WebString& downloadName, bool shouldReplaceCurrentEntry));
+};
+
+class LinkSelectionTest : public SelectionTestBase {
+protected:
+ void SetUp() override
+ {
+ static const char* kHTMLString =
+ "<a id='link' href='foo.com' style='font-size:20pt'>Text to select foobar</a>"
+ "<div id='page_text'>Lorem ipsum dolor sit amet</div>";
+
+ // We need to set deviceSupportsMouse setting to true and page's focus controller to active
+ // so that FrameView can set the mouse cursor.
+ m_webView = m_helper.initialize(false, &m_testFrameClient, nullptr,
+ [](WebSettings* settings) { settings->setDeviceSupportsMouse(true); });
+ m_mainFrame = m_webView->mainFrameImpl();
+ FrameTestHelpers::loadHTMLString(m_mainFrame, kHTMLString, URLTestHelpers::toKURL("http://foobar.com"));
+ m_webView->resize(WebSize(800, 600));
+ m_webView->page()->focusController().setActive(true);
+
+ auto* document = m_mainFrame->frame()->document();
+ ASSERT(document);
+ auto* linkToSelect = document->getElementById("link")->firstChild();
+ ASSERT(linkToSelect);
+ // We get larger range that we actually want to select, because we need a slightly larger
+ // rect to include the last character to the selection.
+ const auto rangeToSelect = Range::create(*document, linkToSelect, 5, linkToSelect, 16);
+
+ const auto& selectionRect = rangeToSelect->boundingBox();
+ const auto& selectionRectCenterY = selectionRect.center().y();
+ m_leftPointInLink = selectionRect.minXMinYCorner();
+ m_leftPointInLink.setY(selectionRectCenterY);
+
+ m_rightPointInLink = selectionRect.maxXMinYCorner();
+ m_rightPointInLink.setY(selectionRectCenterY);
+ m_rightPointInLink.move(-2, 0);
+ }
+
+ TestFrameClient m_testFrameClient;
+ IntPoint m_leftPointInLink;
+ IntPoint m_rightPointInLink;
+};
+
+TEST_F(LinkSelectionTest, MouseDragWithoutAltAllowNoLinkSelection)
+{
+ emulateMouseDrag(m_leftPointInLink, m_rightPointInLink, 0);
+ EXPECT_EQ(std::string(), getSelectionText());
+}
+
+TEST_F(LinkSelectionTest, MouseDragWithAltAllowSelection)
+{
+ emulateMouseDrag(m_leftPointInLink, m_rightPointInLink, WebInputEvent::AltKey);
+ EXPECT_EQ("to select", getSelectionText());
+}
+
+TEST_F(LinkSelectionTest, HandCursorDuringLinkDrag)
+{
+ emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, 0,
+ true /* sendDownEvent */, false /* sendUpEvent */);
yosin_UTC9 2016/03/10 01:40:48 How about writing this as: const bool sendDownEve
+ m_mainFrame->frame()->localFrameRoot()->eventHandler().scheduleCursorUpdate();
+ testing::waitForDeferredTasks(0.05);
+ const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTesting();
+ EXPECT_EQ(Cursor::Hand, cursor.getType());
+}
+
+TEST_F(LinkSelectionTest, CaretCursorOverLinkDuringSelection)
+{
+ emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, WebInputEvent::AltKey,
+ true /* sendDownEvent */, false /* sendUpEvent */);
+ m_mainFrame->frame()->localFrameRoot()->eventHandler().scheduleCursorUpdate();
+ testing::waitForDeferredTasks(0.05);
+ const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTesting();
+ EXPECT_EQ(Cursor::IBeam, cursor.getType());
+}
+
+TEST_F(LinkSelectionTest, HandCursorOverLinkAfterContextMenu)
+{
+ // Move mouse.
+ emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, 0,
+ false /* sendDownEvent */, false /* sendUpEvent */);
+
+ // Show context menu. We don't send mouseup event here since in browser it doesn't reach
+ // blink because of shown context menu.
+ emulateMouseDown(m_leftPointInLink, WebMouseEvent::ButtonRight, 0, 1);
+
+ LocalFrame* frame = m_mainFrame->frame();
+ // Hide context menu.
+ frame->page()->contextMenuController().clearContextMenu();
+
+ frame->localFrameRoot()->eventHandler().scheduleCursorUpdate();
+ testing::waitForDeferredTasks(0.05);
+ const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTesting();
+ EXPECT_EQ(Cursor::Hand, cursor.getType());
+}
+
+TEST_F(LinkSelectionTest, SingleClickWithAltStartsDownload)
+{
+ EXPECT_CALL(m_testFrameClient, loadURLExternally(_, WebNavigationPolicy::WebNavigationPolicyDownload, WebString(), _));
+ emulateMouseClick(m_leftPointInLink, WebMouseEvent::ButtonLeft, WebInputEvent::AltKey);
+}
+
+TEST_F(LinkSelectionTest, SingleClickWithAltStartsDownloadWhenTextSelected)
+{
+ auto* document = m_mainFrame->frame()->document();
+ auto* textToSelect = document->getElementById("page_text")->firstChild();
+ ASSERT(textToSelect);
+
+ // Select some page text outside the link element.
+ const RefPtrWillBeRawPtr<Range> rangeToSelect = Range::create(*document, textToSelect, 1, textToSelect, 20);
+ const auto& selectionRect = rangeToSelect->boundingBox();
+ m_mainFrame->moveRangeSelection(selectionRect.minXMinYCorner(), selectionRect.maxXMaxYCorner());
+ EXPECT_FALSE(getSelectionText().empty());
+
+ EXPECT_CALL(m_testFrameClient, loadURLExternally(_, WebNavigationPolicy::WebNavigationPolicyDownload, WebString(), _));
+ emulateMouseClick(m_leftPointInLink, WebMouseEvent::ButtonLeft, WebInputEvent::AltKey);
+}
+
+class ClickEventsBugTest : public SelectionTestBase {
+protected:
+ class MockEventListener final : public EventListener {
+ public:
+ static PassRefPtrWillBeRawPtr<MockEventListener> create()
+ {
+ return adoptRefWillBeNoop(new MockEventListener());
+ }
+
+ bool operator==(const EventListener& other) const final
+ {
+ return this == &other;
+ }
+
+ MOCK_METHOD2(handleEvent, void(ExecutionContext* executionContext, Event*));
+
+ private:
+ MockEventListener() : EventListener(CPPEventListenerType)
+ {
+ }
+ };
+
+ void SetUp() override
+ {
+ static const char* kHTMLString =
+ "<div id='empty_div' style='width: 100px; height: 100px;'></div>"
+ "<span id='text_div'>Sometexttoshow</span>";
+
+ m_webView = m_helper.initialize(false);
+ m_mainFrame = m_webView->mainFrameImpl();
+ FrameTestHelpers::loadHTMLString(m_mainFrame, kHTMLString, URLTestHelpers::toKURL("http://foobar.com"));
+ m_webView->resize(WebSize(800, 600));
+ m_webView->page()->focusController().setActive(true);
+
+ auto* document = m_mainFrame->frame()->document();
+ ASSERT(document);
+
+ auto* emptyDiv = document->getElementById("empty_div");
+ auto* textDiv = document->getElementById("text_div");
+ ASSERT_TRUE(emptyDiv);
+ ASSERT_TRUE(textDiv);
+ }
+
+ void checkMouseClicks(Element& element, bool doubleClickEvent)
+ {
+ struct ScopedListenersCleaner {
+ ScopedListenersCleaner(Element* element) : m_element(element) {}
+
+ ~ScopedListenersCleaner()
+ {
+ m_element->removeAllEventListeners();
+ }
+
+ RawPtrWillBePersistent<Element> m_element;
+ } const listenersCleaner(&element);
+
+ RefPtrWillBeRawPtr<MockEventListener> eventHandler = MockEventListener::create();
+ element.addEventListener(
+ doubleClickEvent ? EventTypeNames::dblclick : EventTypeNames::click,
+ eventHandler);
+
+ ::testing::InSequence s;
+ EXPECT_CALL(*eventHandler, handleEvent(_, _)).Times(1);
+
+ const auto& elemBounds = element.boundsInViewport();
+ const int clickCount = doubleClickEvent ? 2 : 1;
+ emulateMouseClick(elemBounds.center(), WebMouseEvent::ButtonLeft, 0, clickCount);
+
+ if (doubleClickEvent) {
+ EXPECT_EQ(element.innerText().isEmpty(), getSelectionText().empty());
+ }
+ }
+};
+
+TEST_F(ClickEventsBugTest, SingleAndDoubleClickWillBeHandled)
+{
+ auto* document = m_mainFrame->frame()->document();
+ auto* element = document->getElementById("empty_div");
+
+ {
+ SCOPED_TRACE("Empty div, single click");
+ checkMouseClicks(*element, false);
+ }
+
+ {
+ SCOPED_TRACE("Empty div, double click");
+ checkMouseClicks(*element, true);
+ }
+
+ element = document->getElementById("text_div");
+
+ {
+ SCOPED_TRACE("Text div, single click");
+ checkMouseClicks(*element, false);
+ }
+
+ {
+ SCOPED_TRACE("Text div, double click");
+ checkMouseClicks(*element, true);
+ }
+}
+} // namespace
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698