1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
// Copyright (c) 2011 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 "base/strings/utf_string_conversions.h"
#include "content/common/frame_messages.h"
#include "content/public/test/render_view_test.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/WebKit/public/platform/WebSize.h"
// Tests for the external select popup menu (Mac specific).
namespace content {
namespace {
const char* const kSelectID = "mySelect";
const char* const kEmptySelectID = "myEmptySelect";
} // namespace
class ExternalPopupMenuTest : public RenderViewTest {
public:
ExternalPopupMenuTest() {}
RenderViewImpl* view() {
return static_cast<RenderViewImpl*>(view_);
}
RenderFrameImpl* frame() {
return view()->GetMainRenderFrame();
}
void SetUp() override {
RenderViewTest::SetUp();
// We need to set this explictly as RenderMain is not run.
blink::WebView::setUseExternalPopupMenus(true);
std::string html = "<select id='mySelect' onchange='selectChanged(this)'>"
" <option>zero</option>"
" <option selected='1'>one</option>"
" <option>two</option>"
"</select>"
"<select id='myEmptySelect'>"
"</select>";
if (ShouldRemoveSelectOnChange()) {
html += "<script>"
" function selectChanged(select) {"
" select.parentNode.removeChild(select);"
" }"
"</script>";
}
// Load the test page.
LoadHTML(html.c_str());
// Set a minimum size and give focus so simulated events work.
view()->webwidget()->resize(blink::WebSize(500, 500));
view()->webwidget()->setFocus(true);
}
int GetSelectedIndex() {
base::string16 script(base::ASCIIToUTF16(kSelectID));
script.append(base::ASCIIToUTF16(".selectedIndex"));
int selected_index = -1;
ExecuteJavaScriptAndReturnIntValue(script, &selected_index);
return selected_index;
}
protected:
virtual bool ShouldRemoveSelectOnChange() const { return false; }
DISALLOW_COPY_AND_ASSIGN(ExternalPopupMenuTest);
};
// Normal case: test showing a select popup, canceling/selecting an item.
TEST_F(ExternalPopupMenuTest, NormalCase) {
IPC::TestSink& sink = render_thread_->sink();
// Click the text field once.
EXPECT_TRUE(SimulateElementClick(kSelectID));
// We should have sent a message to the browser to show the popup menu.
const IPC::Message* message =
sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
ASSERT_TRUE(message != NULL);
Tuple<FrameHostMsg_ShowPopup_Params> param;
FrameHostMsg_ShowPopup::Read(message, ¶m);
ASSERT_EQ(3U, get<0>(param).popup_items.size());
EXPECT_EQ(1, get<0>(param).selected_item);
// Simulate the user canceling the popup; the index should not have changed.
frame()->OnSelectPopupMenuItem(-1);
EXPECT_EQ(1, GetSelectedIndex());
// Show the pop-up again and this time make a selection.
EXPECT_TRUE(SimulateElementClick(kSelectID));
frame()->OnSelectPopupMenuItem(0);
EXPECT_EQ(0, GetSelectedIndex());
// Show the pop-up again and make another selection.
sink.ClearMessages();
EXPECT_TRUE(SimulateElementClick(kSelectID));
message = sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
ASSERT_TRUE(message != NULL);
FrameHostMsg_ShowPopup::Read(message, ¶m);
ASSERT_EQ(3U, get<0>(param).popup_items.size());
EXPECT_EQ(0, get<0>(param).selected_item);
}
// Page shows popup, then navigates away while popup showing, then select.
TEST_F(ExternalPopupMenuTest, ShowPopupThenNavigate) {
// Click the text field once.
EXPECT_TRUE(SimulateElementClick(kSelectID));
// Now we navigate to another pager.
LoadHTML("<blink>Awesome page!</blink>");
// Now the user selects something, we should not crash.
frame()->OnSelectPopupMenuItem(-1);
}
// An empty select should not cause a crash when clicked.
// http://crbug.com/63774
TEST_F(ExternalPopupMenuTest, EmptySelect) {
EXPECT_TRUE(SimulateElementClick(kEmptySelectID));
}
class ExternalPopupMenuRemoveTest : public ExternalPopupMenuTest {
public:
ExternalPopupMenuRemoveTest() {}
protected:
bool ShouldRemoveSelectOnChange() const override { return true; }
};
// Tests that nothing bad happen when the page removes the select when it
// changes. (http://crbug.com/61997)
TEST_F(ExternalPopupMenuRemoveTest, RemoveOnChange) {
// Click the text field once to show the popup.
EXPECT_TRUE(SimulateElementClick(kSelectID));
// Select something, it causes the select to be removed from the page.
frame()->OnSelectPopupMenuItem(0);
// Just to check the soundness of the test, call SimulateElementClick again.
// It should return false as the select has been removed.
EXPECT_FALSE(SimulateElementClick(kSelectID));
}
class ExternalPopupMenuDisplayNoneTest : public ExternalPopupMenuTest {
public:
ExternalPopupMenuDisplayNoneTest() {}
void SetUp() override {
RenderViewTest::SetUp();
// We need to set this explictly as RenderMain is not run.
blink::WebView::setUseExternalPopupMenus(true);
std::string html = "<select id='mySelect'>"
" <option value='zero'>zero</option>"
" <optgroup label='hide' style='display: none'>"
" <option value='one'>one</option>"
" </optgroup>"
" <option value='two'>two</option>"
" <option value='three'>three</option>"
" <option value='four'>four</option>"
" <option value='five'>five</option>"
"</select>";
// Load the test page.
LoadHTML(html.c_str());
// Set a minimum size and give focus so simulated events work.
view()->webwidget()->resize(blink::WebSize(500, 500));
view()->webwidget()->setFocus(true);
}
};
TEST_F(ExternalPopupMenuDisplayNoneTest, SelectItem) {
IPC::TestSink& sink = render_thread_->sink();
// Click the text field once to show the popup.
EXPECT_TRUE(SimulateElementClick(kSelectID));
// Read the message sent to browser to show the popup menu.
const IPC::Message* message =
sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
ASSERT_TRUE(message != NULL);
Tuple<FrameHostMsg_ShowPopup_Params> param;
FrameHostMsg_ShowPopup::Read(message, ¶m);
// Number of items should match item count minus the number
// of "display: none" items.
ASSERT_EQ(5U, get<0>(param).popup_items.size());
// Select index 1 item. This should select item with index 2,
// skipping the item with 'display: none'
frame()->OnSelectPopupMenuItem(1);
EXPECT_EQ(2, GetSelectedIndex());
}
} // namespace content
|