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..b9ffc6352c6b62ee16ecc64f2d0d796739093d92 |
--- /dev/null |
+++ b/third_party/WebKit/Source/web/tests/LinkSelectionTest.cpp |
@@ -0,0 +1,245 @@ |
+// 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> |
tkent
2016/03/25 03:33:03
Please include it with "", not <>.
Please specify
|
+#include <gtest/gtest.h> |
+ |
+using ::testing::_; |
+ |
+namespace blink { |
+ |
+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 |
+ { |
+ const char* const 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); |
tkent
2016/03/25 03:33:02
Blink's ASSERT() is deprecated. Use glog's DCHECK
|
+ auto* linkToSelect = document->getElementById("link")->firstChild(); |
+ ASSERT(linkToSelect); |
tkent
2016/03/25 03:33:02
ASSERT() is deprecated.
|
+ // 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, SendDownEvent); |
+ m_mainFrame->frame()->localFrameRoot()->eventHandler().scheduleCursorUpdate(); |
+ testing::runDelayedTasks(50); |
+ 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, SendDownEvent); |
+ m_mainFrame->frame()->localFrameRoot()->eventHandler().scheduleCursorUpdate(); |
+ testing::runDelayedTasks(50); |
+ 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, 0); |
+ |
+ // 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::runDelayedTasks(50); |
+ 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); |
tkent
2016/03/25 03:33:03
ASSERT() is deprecated.
|
+ |
+ // 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 LinkSelectionClickEvents : public SelectionTestBase { |
tkent
2016/03/25 03:33:03
Please use "Test" suffix for test fixture class na
|
+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 |
+ { |
+ const char* const 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); |
tkent
2016/03/25 03:33:03
ASSERT() is deprecated.
|
+ |
+ auto* emptyDiv = document->getElementById("empty_div"); |
+ auto* textDiv = document->getElementById("text_div"); |
+ ASSERT_TRUE(emptyDiv); |
tkent
2016/03/25 03:33:03
ASSERT_NE(nullptr, emptyDiv), or DCHECK_NE(emptyDi
|
+ ASSERT_TRUE(textDiv); |
tkent
2016/03/25 03:33:03
Ditto.
|
+ } |
+ |
+ 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(LinkSelectionClickEvents, 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 blink |