blob: d3a098f28e17df52b875b819050b391bdc4214af [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 "core/html/forms/ExternalPopupMenu.h"
#include <memory>
#include "core/HTMLNames.h"
#include "core/frame/FrameTestHelpers.h"
#include "core/frame/VisualViewport.h"
#include "core/frame/WebLocalFrameBase.h"
#include "core/html/HTMLSelectElement.h"
#include "core/html/forms/PopupMenu.h"
#include "core/layout/LayoutMenuList.h"
#include "core/page/Page.h"
#include "core/testing/DummyPageHolder.h"
#include "platform/testing/URLTestHelpers.h"
#include "platform/testing/UnitTestHelpers.h"
#include "public/platform/Platform.h"
#include "public/platform/WebURLLoaderMockFactory.h"
#include "public/web/WebExternalPopupMenu.h"
#include "public/web/WebPopupMenuInfo.h"
#include "public/web/WebSettings.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
class ExternalPopupMenuDisplayNoneItemsTest : public ::testing::Test {
public:
ExternalPopupMenuDisplayNoneItemsTest() {}
protected:
void SetUp() override {
dummy_page_holder_ = DummyPageHolder::Create(IntSize(800, 600));
HTMLSelectElement* element =
HTMLSelectElement::Create(dummy_page_holder_->GetDocument());
// 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>");
dummy_page_holder_->GetDocument().body()->AppendChild(element,
ASSERT_NO_EXCEPTION);
owner_element_ = element;
dummy_page_holder_->GetDocument()
.UpdateStyleAndLayoutIgnorePendingStylesheets();
}
std::unique_ptr<DummyPageHolder> dummy_page_holder_;
Persistent<HTMLSelectElement> owner_element_;
};
TEST_F(ExternalPopupMenuDisplayNoneItemsTest, PopupMenuInfoSizeTest) {
WebPopupMenuInfo info;
ExternalPopupMenu::GetPopupMenuInfo(info, *owner_element_);
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, *owner_element_));
EXPECT_EQ(6, ExternalPopupMenu::ToPopupMenuItemIndex(4, *owner_element_));
// Invalid index, methods should return -1.
EXPECT_EQ(
-1, ExternalPopupMenu::ToExternalPopupMenuItemIndex(8, *owner_element_));
EXPECT_EQ(-1, ExternalPopupMenu::ToPopupMenuItemIndex(8, *owner_element_));
}
class ExternalPopupMenuWebFrameClient
: public FrameTestHelpers::TestWebFrameClient {
public:
WebExternalPopupMenu* CreateExternalPopupMenu(
const WebPopupMenuInfo&,
WebExternalPopupMenuClient*) override {
return &mock_web_external_popup_menu_;
}
WebRect ShownBounds() const {
return mock_web_external_popup_menu_.ShownBounds();
}
private:
class MockWebExternalPopupMenu : public WebExternalPopupMenu {
void Show(const WebRect& bounds) override { shown_bounds_ = bounds; }
void Close() override {}
public:
WebRect ShownBounds() const { return shown_bounds_; }
private:
WebRect shown_bounds_;
};
WebRect shown_bounds_;
MockWebExternalPopupMenu mock_web_external_popup_menu_;
};
class ExternalPopupMenuTest : public ::testing::Test {
public:
ExternalPopupMenuTest() : base_url_("http://www.test.com") {}
protected:
void SetUp() override {
helper_.Initialize(&web_frame_client_);
WebView()->SetUseExternalPopupMenus(true);
}
void TearDown() override {
Platform::Current()
->GetURLLoaderMockFactory()
->UnregisterAllURLsAndClearMemoryCache();
}
void RegisterMockedURLLoad(const std::string& file_name) {
URLTestHelpers::RegisterMockedURLLoadFromBase(
WebString::FromUTF8(base_url_), testing::WebTestDataPath("popup"),
WebString::FromUTF8(file_name), WebString::FromUTF8("text/html"));
}
void LoadFrame(const std::string& file_name) {
FrameTestHelpers::LoadFrame(MainFrame(), base_url_ + file_name);
WebView()->Resize(WebSize(800, 600));
WebView()->UpdateAllLifecyclePhases();
}
WebViewBase* WebView() const { return helper_.WebView(); }
const ExternalPopupMenuWebFrameClient& Client() const {
return web_frame_client_;
}
WebLocalFrameBase* MainFrame() const { return helper_.LocalMainFrame(); }
private:
std::string base_url_;
ExternalPopupMenuWebFrameClient web_frame_client_;
FrameTestHelpers::WebViewHelper helper_;
};
TEST_F(ExternalPopupMenuTest, PopupAccountsForVisualViewportTransform) {
RegisterMockedURLLoad("select_mid_screen.html");
LoadFrame("select_mid_screen.html");
WebView()->Resize(WebSize(100, 100));
WebView()->UpdateAllLifecyclePhases();
HTMLSelectElement* select = toHTMLSelectElement(
MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
LayoutMenuList* menu_list = ToLayoutMenuList(select->GetLayoutObject());
ASSERT_TRUE(menu_list);
VisualViewport& visual_viewport = WebView()->GetPage()->GetVisualViewport();
IntRect rect_in_document = menu_list->AbsoluteBoundingBoxRect();
constexpr int kScaleFactor = 2;
ScrollOffset scroll_delta(20, 30);
const int expected_x =
(rect_in_document.X() - scroll_delta.Width()) * kScaleFactor;
const int expected_y =
(rect_in_document.Y() - scroll_delta.Height()) * kScaleFactor;
WebView()->SetPageScaleFactor(kScaleFactor);
visual_viewport.Move(scroll_delta);
select->ShowPopup();
EXPECT_EQ(expected_x, Client().ShownBounds().x);
EXPECT_EQ(expected_y, Client().ShownBounds().y);
}
TEST_F(ExternalPopupMenuTest, DidAcceptIndex) {
RegisterMockedURLLoad("select.html");
LoadFrame("select.html");
HTMLSelectElement* select = toHTMLSelectElement(
MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
LayoutMenuList* menu_list = ToLayoutMenuList(select->GetLayoutObject());
ASSERT_TRUE(menu_list);
select->ShowPopup();
ASSERT_TRUE(select->PopupIsVisible());
WebExternalPopupMenuClient* client =
static_cast<ExternalPopupMenu*>(select->Popup());
client->DidAcceptIndex(2);
EXPECT_FALSE(select->PopupIsVisible());
ASSERT_STREQ("2", menu_list->GetText().Utf8().data());
EXPECT_EQ(2, select->selectedIndex());
}
TEST_F(ExternalPopupMenuTest, DidAcceptIndices) {
RegisterMockedURLLoad("select.html");
LoadFrame("select.html");
HTMLSelectElement* select = toHTMLSelectElement(
MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
LayoutMenuList* menu_list = ToLayoutMenuList(select->GetLayoutObject());
ASSERT_TRUE(menu_list);
select->ShowPopup();
ASSERT_TRUE(select->PopupIsVisible());
WebExternalPopupMenuClient* client =
static_cast<ExternalPopupMenu*>(select->Popup());
int indices[] = {2};
WebVector<int> indices_vector(indices, 1);
client->DidAcceptIndices(indices_vector);
EXPECT_FALSE(select->PopupIsVisible());
EXPECT_STREQ("2", menu_list->GetText().Utf8().data());
EXPECT_EQ(2, select->selectedIndex());
}
TEST_F(ExternalPopupMenuTest, DidAcceptIndicesClearSelect) {
RegisterMockedURLLoad("select.html");
LoadFrame("select.html");
HTMLSelectElement* select = toHTMLSelectElement(
MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
LayoutMenuList* menu_list = ToLayoutMenuList(select->GetLayoutObject());
ASSERT_TRUE(menu_list);
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