blob: 4b3b9b8cbe2e1f73d2e70dfdbb3e2ee4a3901cdc [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 "third_party/blink/renderer/core/html/forms/external_popup_menu.h"
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_external_popup_menu.h"
#include "third_party/blink/public/web/web_popup_menu_info.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_menu_list.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
namespace blink {
class ExternalPopupMenuDisplayNoneItemsTest : public PageTestBase {
public:
ExternalPopupMenuDisplayNoneItemsTest() = default;
protected:
void SetUp() override {
PageTestBase::SetUp();
HTMLSelectElement* element = HTMLSelectElement::Create(GetDocument());
// Set the 4th an 5th items to have "display: none" property
element->SetInnerHTMLFromString(
"<option><option><option><option style='display:none;'><option "
"style='display:none;'><option><option>");
GetDocument().body()->AppendChild(element, ASSERT_NO_EXCEPTION);
owner_element_ = element;
GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
}
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 frame_test_helpers::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) {
url_test_helpers::RegisterMockedURLLoadFromBase(
WebString::FromUTF8(base_url_), test::CoreTestDataPath("popup"),
WebString::FromUTF8(file_name), WebString::FromUTF8("text/html"));
}
void LoadFrame(const std::string& file_name) {
frame_test_helpers::LoadFrame(MainFrame(), base_url_ + file_name);
WebView()->MainFrameWidget()->Resize(WebSize(800, 600));
WebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
}
WebViewImpl* WebView() const { return helper_.GetWebView(); }
const ExternalPopupMenuWebFrameClient& Client() const {
return web_frame_client_;
}
WebLocalFrameImpl* MainFrame() const { return helper_.LocalMainFrame(); }
private:
std::string base_url_;
ExternalPopupMenuWebFrameClient web_frame_client_;
frame_test_helpers::WebViewHelper helper_;
};
TEST_F(ExternalPopupMenuTest, PopupAccountsForVisualViewportTransform) {
RegisterMockedURLLoad("select_mid_screen.html");
LoadFrame("select_mid_screen.html");
WebView()->MainFrameWidget()->Resize(WebSize(100, 100));
WebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
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