blob: a0b5a4370baed599de7116f271b15d6c4c74a94c [file] [log] [blame]
// Copyright (c) 2014 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 "web/ExternalPopupMenu.h"
#include "core/HTMLNames.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/frame/FrameHost.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLSelectElement.h"
#include "core/layout/LayoutMenuList.h"
#include "core/page/Page.h"
#include "core/testing/DummyPageHolder.h"
#include "platform/PopupMenu.h"
#include "platform/testing/URLTestHelpers.h"
#include "public/platform/Platform.h"
#include "public/platform/WebURLLoaderMockFactory.h"
#include "public/web/WebCache.h"
#include "public/web/WebExternalPopupMenu.h"
#include "public/web/WebPopupMenuInfo.h"
#include "public/web/WebSettings.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "web/WebLocalFrameImpl.h"
#include "web/tests/FrameTestHelpers.h"
namespace blink {
class ExternalPopupMenuDisplayNoneItemsTest : public testing::Test {
public:
ExternalPopupMenuDisplayNoneItemsTest() { }
protected:
void SetUp() override
{
m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600));
HTMLSelectElement* element = HTMLSelectElement::create(m_dummyPageHolder->document());
// Set the 4th an 5th items to have "display: none" property
element->setInnerHTML("<option><option><option><option style='display:none;'><option style='display:none;'><option><option>", ASSERT_NO_EXCEPTION);
m_dummyPageHolder->document().body()->appendChild(element, ASSERT_NO_EXCEPTION);
m_ownerElement = element;
m_dummyPageHolder->document().updateLayoutIgnorePendingStylesheets();
}
OwnPtr<DummyPageHolder> m_dummyPageHolder;
Persistent<HTMLSelectElement> m_ownerElement;
};
TEST_F(ExternalPopupMenuDisplayNoneItemsTest, PopupMenuInfoSizeTest)
{
WebPopupMenuInfo info;
ExternalPopupMenu::getPopupMenuInfo(info, *m_ownerElement);
EXPECT_EQ(5U, info.items.size());
}
TEST_F(ExternalPopupMenuDisplayNoneItemsTest, IndexMappingTest)
{
// 6th indexed item in popupmenu would be the 4th item in ExternalPopupMenu,
// and vice-versa.
EXPECT_EQ(4, ExternalPopupMenu::toExternalPopupMenuItemIndex(6, *m_ownerElement));
EXPECT_EQ(6, ExternalPopupMenu::toPopupMenuItemIndex(4, *m_ownerElement));
// Invalid index, methods should return -1.
EXPECT_EQ(-1, ExternalPopupMenu::toExternalPopupMenuItemIndex(8, *m_ownerElement));
EXPECT_EQ(-1, ExternalPopupMenu::toPopupMenuItemIndex(8, *m_ownerElement));
}
class ExternalPopupMenuWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
public:
WebExternalPopupMenu* createExternalPopupMenu(const WebPopupMenuInfo&, WebExternalPopupMenuClient*) override
{
return &m_mockWebExternalPopupMenu;
}
WebRect shownBounds() const
{
return m_mockWebExternalPopupMenu.shownBounds();
}
private:
class MockWebExternalPopupMenu : public WebExternalPopupMenu {
void show(const WebRect& bounds) override
{
m_shownBounds = bounds;
}
void close() override { }
public:
WebRect shownBounds() const
{
return m_shownBounds;
}
private:
WebRect m_shownBounds;
};
WebRect m_shownBounds;
MockWebExternalPopupMenu m_mockWebExternalPopupMenu;
};
class ExternalPopupMenuTest : public testing::Test {
public:
ExternalPopupMenuTest() : m_baseURL("http://www.test.com") { }
protected:
void SetUp() override
{
m_helper.initialize(false, &m_webFrameClient, &m_webViewClient);
webView()->setUseExternalPopupMenus(true);
}
void TearDown() override
{
Platform::current()->getURLLoaderMockFactory()->unregisterAllURLs();
WebCache::clear();
}
void registerMockedURLLoad(const std::string& fileName)
{
URLTestHelpers::registerMockedURLLoad(URLTestHelpers::toKURL(m_baseURL + fileName), WebString::fromUTF8(fileName.c_str()), WebString::fromUTF8("popup/"), WebString::fromUTF8("text/html"));
}
void loadFrame(const std::string& fileName)
{
FrameTestHelpers::loadFrame(mainFrame(), m_baseURL + fileName);
webView()->resize(WebSize(800, 600));
webView()->updateAllLifecyclePhases();
}
WebViewImpl* webView() const { return m_helper.webViewImpl(); }
const ExternalPopupMenuWebFrameClient& client() const { return m_webFrameClient; }
WebLocalFrameImpl* mainFrame() const { return m_helper.webViewImpl()->mainFrameImpl(); }
private:
std::string m_baseURL;
FrameTestHelpers::TestWebViewClient m_webViewClient;
ExternalPopupMenuWebFrameClient m_webFrameClient;
FrameTestHelpers::WebViewHelper m_helper;
};
TEST_F(ExternalPopupMenuTest, PopupAccountsForVisualViewportOffset)
{
registerMockedURLLoad("select_mid_screen.html");
loadFrame("select_mid_screen.html");
webView()->resize(WebSize(100, 100));
webView()->updateAllLifecyclePhases();
HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select"));
LayoutMenuList* menuList = toLayoutMenuList(select->layoutObject());
ASSERT_TRUE(menuList);
VisualViewport& visualViewport = webView()->page()->frameHost().visualViewport();
IntRect rectInDocument = menuList->absoluteBoundingBoxRect();
webView()->setPageScaleFactor(2);
IntPoint scrollDelta(20, 30);
visualViewport.move(scrollDelta);
select->showPopup();
EXPECT_EQ(rectInDocument.x() - scrollDelta.x(), client().shownBounds().x);
EXPECT_EQ(rectInDocument.y() - scrollDelta.y(), client().shownBounds().y);
}
TEST_F(ExternalPopupMenuTest, DidAcceptIndex)
{
registerMockedURLLoad("select.html");
loadFrame("select.html");
HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select"));
LayoutMenuList* menuList = toLayoutMenuList(select->layoutObject());
ASSERT_TRUE(menuList);
select->showPopup();
ASSERT_TRUE(select->popupIsVisible());
WebExternalPopupMenuClient* client = static_cast<ExternalPopupMenu*>(select->popup());
client->didAcceptIndex(2);
EXPECT_FALSE(select->popupIsVisible());
ASSERT_STREQ("2", menuList->text().utf8().data());
EXPECT_EQ(2, select->selectedIndex());
}
TEST_F(ExternalPopupMenuTest, DidAcceptIndices)
{
registerMockedURLLoad("select.html");
loadFrame("select.html");
HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select"));
LayoutMenuList* menuList = toLayoutMenuList(select->layoutObject());
ASSERT_TRUE(menuList);
select->showPopup();
ASSERT_TRUE(select->popupIsVisible());
WebExternalPopupMenuClient* client = static_cast<ExternalPopupMenu*>(select->popup());
int indices[] = { 2 };
WebVector<int> indicesVector(indices, 1);
client->didAcceptIndices(indicesVector);
EXPECT_FALSE(select->popupIsVisible());
EXPECT_STREQ("2", menuList->text().utf8().data());
EXPECT_EQ(2, select->selectedIndex());
}
TEST_F(ExternalPopupMenuTest, DidAcceptIndicesClearSelect)
{
registerMockedURLLoad("select.html");
loadFrame("select.html");
HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select"));
LayoutMenuList* menuList = toLayoutMenuList(select->layoutObject());
ASSERT_TRUE(menuList);
select->showPopup();
ASSERT_TRUE(select->popupIsVisible());
WebExternalPopupMenuClient* client = static_cast<ExternalPopupMenu*>(select->popup());
WebVector<int> indices;
client->didAcceptIndices(indices);
EXPECT_FALSE(select->popupIsVisible());
EXPECT_EQ(-1, select->selectedIndex());
}
} // namespace blink