Chromium Code Reviews| 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 |