blob: e58d764caff5967441a052dd5123d2f59f93f82d [file] [log] [blame]
[email protected]c6d068ff2011-10-14 17:28:231// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]caf706f2010-10-26 17:54:082// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]74ebfb12013-06-07 20:48:005#include "base/strings/utf_string_conversions.h"
avi485e5fd62014-08-25 23:26:146#include "content/common/frame_messages.h"
[email protected]899617f2012-06-04 02:27:147#include "content/public/test/render_view_test.h"
avi485e5fd62014-08-25 23:26:148#include "content/renderer/render_frame_impl.h"
[email protected]068970d2011-10-11 00:05:169#include "content/renderer/render_view_impl.h"
[email protected]caf706f2010-10-26 17:54:0810#include "testing/gtest/include/gtest/gtest.h"
[email protected]2255a9332013-06-17 05:12:3111#include "third_party/WebKit/public/web/WebView.h"
[email protected]74ebfb12013-06-07 20:48:0012#include "third_party/WebKit/public/platform/WebSize.h"
[email protected]caf706f2010-10-26 17:54:0813
14// Tests for the external select popup menu (Mac specific).
15
[email protected]e9ff79c2012-10-19 21:31:2616namespace content {
[email protected]caf706f2010-10-26 17:54:0817namespace {
18
19const char* const kSelectID = "mySelect";
[email protected]92ccbdd2010-12-01 19:30:4420const char* const kEmptySelectID = "myEmptySelect";
[email protected]caf706f2010-10-26 17:54:0821
22} // namespace
23
[email protected]e9ff79c2012-10-19 21:31:2624class ExternalPopupMenuTest : public RenderViewTest {
[email protected]caf706f2010-10-26 17:54:0825 public:
26 ExternalPopupMenuTest() {}
27
[email protected]068970d2011-10-11 00:05:1628 RenderViewImpl* view() {
29 return static_cast<RenderViewImpl*>(view_);
30 }
31
avi485e5fd62014-08-25 23:26:1432 RenderFrameImpl* frame() {
mostynbc33353232014-09-12 09:38:3133 return view()->GetMainRenderFrame();
avi485e5fd62014-08-25 23:26:1434 }
35
[email protected]caf706f2010-10-26 17:54:0836 virtual void SetUp() {
[email protected]e9ff79c2012-10-19 21:31:2637 RenderViewTest::SetUp();
[email protected]caf706f2010-10-26 17:54:0838 // We need to set this explictly as RenderMain is not run.
[email protected]180ef242013-11-07 06:50:4639 blink::WebView::setUseExternalPopupMenus(true);
[email protected]caf706f2010-10-26 17:54:0840
[email protected]360bc0b12010-11-11 19:21:2641 std::string html = "<select id='mySelect' onchange='selectChanged(this)'>"
42 " <option>zero</option>"
43 " <option selected='1'>one</option>"
44 " <option>two</option>"
[email protected]92ccbdd2010-12-01 19:30:4445 "</select>"
46 "<select id='myEmptySelect'>"
[email protected]360bc0b12010-11-11 19:21:2647 "</select>";
48 if (ShouldRemoveSelectOnChange()) {
49 html += "<script>"
50 " function selectChanged(select) {"
51 " select.parentNode.removeChild(select);"
52 " }"
53 "</script>";
54 }
55
[email protected]caf706f2010-10-26 17:54:0856 // Load the test page.
[email protected]360bc0b12010-11-11 19:21:2657 LoadHTML(html.c_str());
[email protected]caf706f2010-10-26 17:54:0858
59 // Set a minimum size and give focus so simulated events work.
[email protected]180ef242013-11-07 06:50:4660 view()->webwidget()->resize(blink::WebSize(500, 500));
[email protected]068970d2011-10-11 00:05:1661 view()->webwidget()->setFocus(true);
[email protected]caf706f2010-10-26 17:54:0862 }
63
64 int GetSelectedIndex() {
[email protected]32956122013-12-25 07:29:2465 base::string16 script(base::ASCIIToUTF16(kSelectID));
66 script.append(base::ASCIIToUTF16(".selectedIndex"));
[email protected]caf706f2010-10-26 17:54:0867 int selected_index = -1;
68 ExecuteJavaScriptAndReturnIntValue(script, &selected_index);
69 return selected_index;
70 }
71
[email protected]360bc0b12010-11-11 19:21:2672 protected:
73 virtual bool ShouldRemoveSelectOnChange() const { return false; }
74
[email protected]caf706f2010-10-26 17:54:0875 DISALLOW_COPY_AND_ASSIGN(ExternalPopupMenuTest);
76};
77
78// Normal case: test showing a select popup, canceling/selecting an item.
79TEST_F(ExternalPopupMenuTest, NormalCase) {
[email protected]c6d068ff2011-10-14 17:28:2380 IPC::TestSink& sink = render_thread_->sink();
[email protected]caf706f2010-10-26 17:54:0881
82 // Click the text field once.
83 EXPECT_TRUE(SimulateElementClick(kSelectID));
84
85 // We should have sent a message to the browser to show the popup menu.
86 const IPC::Message* message =
avi485e5fd62014-08-25 23:26:1487 sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
[email protected]caf706f2010-10-26 17:54:0888 ASSERT_TRUE(message != NULL);
avi485e5fd62014-08-25 23:26:1489 Tuple1<FrameHostMsg_ShowPopup_Params> param;
90 FrameHostMsg_ShowPopup::Read(message, &param);
[email protected]caf706f2010-10-26 17:54:0891 ASSERT_EQ(3U, param.a.popup_items.size());
92 EXPECT_EQ(1, param.a.selected_item);
93
avi485e5fd62014-08-25 23:26:1494 // Simulate the user canceling the popup; the index should not have changed.
95 frame()->OnSelectPopupMenuItem(-1);
[email protected]caf706f2010-10-26 17:54:0896 EXPECT_EQ(1, GetSelectedIndex());
97
98 // Show the pop-up again and this time make a selection.
99 EXPECT_TRUE(SimulateElementClick(kSelectID));
avi485e5fd62014-08-25 23:26:14100 frame()->OnSelectPopupMenuItem(0);
[email protected]caf706f2010-10-26 17:54:08101 EXPECT_EQ(0, GetSelectedIndex());
102
103 // Show the pop-up again and make another selection.
104 sink.ClearMessages();
105 EXPECT_TRUE(SimulateElementClick(kSelectID));
avi485e5fd62014-08-25 23:26:14106 message = sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
[email protected]caf706f2010-10-26 17:54:08107 ASSERT_TRUE(message != NULL);
avi485e5fd62014-08-25 23:26:14108 FrameHostMsg_ShowPopup::Read(message, &param);
[email protected]caf706f2010-10-26 17:54:08109 ASSERT_EQ(3U, param.a.popup_items.size());
110 EXPECT_EQ(0, param.a.selected_item);
111}
112
113// Page shows popup, then navigates away while popup showing, then select.
114TEST_F(ExternalPopupMenuTest, ShowPopupThenNavigate) {
115 // Click the text field once.
116 EXPECT_TRUE(SimulateElementClick(kSelectID));
117
118 // Now we navigate to another pager.
119 LoadHTML("<blink>Awesome page!</blink>");
120
121 // Now the user selects something, we should not crash.
avi485e5fd62014-08-25 23:26:14122 frame()->OnSelectPopupMenuItem(-1);
[email protected]caf706f2010-10-26 17:54:08123}
[email protected]360bc0b12010-11-11 19:21:26124
[email protected]92ccbdd2010-12-01 19:30:44125// An empty select should not cause a crash when clicked.
126// http://crbug.com/63774
127TEST_F(ExternalPopupMenuTest, EmptySelect) {
128 EXPECT_TRUE(SimulateElementClick(kEmptySelectID));
129}
130
[email protected]360bc0b12010-11-11 19:21:26131class ExternalPopupMenuRemoveTest : public ExternalPopupMenuTest {
132 public:
133 ExternalPopupMenuRemoveTest() {}
134
135 protected:
[email protected]6b7fa22d2013-02-20 11:16:21136 virtual bool ShouldRemoveSelectOnChange() const OVERRIDE { return true; }
[email protected]360bc0b12010-11-11 19:21:26137};
138
139// Tests that nothing bad happen when the page removes the select when it
140// changes. (http://crbug.com/61997)
141TEST_F(ExternalPopupMenuRemoveTest, RemoveOnChange) {
142 // Click the text field once to show the popup.
143 EXPECT_TRUE(SimulateElementClick(kSelectID));
144
145 // Select something, it causes the select to be removed from the page.
avi485e5fd62014-08-25 23:26:14146 frame()->OnSelectPopupMenuItem(0);
[email protected]360bc0b12010-11-11 19:21:26147
148 // Just to check the soundness of the test, call SimulateElementClick again.
149 // It should return false as the select has been removed.
150 EXPECT_FALSE(SimulateElementClick(kSelectID));
151}
[email protected]e9ff79c2012-10-19 21:31:26152
[email protected]d0cd67482014-08-12 19:17:12153class ExternalPopupMenuDisplayNoneTest : public ExternalPopupMenuTest {
154 public:
155 ExternalPopupMenuDisplayNoneTest() {}
156
157 virtual void SetUp() {
158 RenderViewTest::SetUp();
159 // We need to set this explictly as RenderMain is not run.
160 blink::WebView::setUseExternalPopupMenus(true);
161
162 std::string html = "<select id='mySelect'>"
163 " <option value='zero'>zero</option>"
164 " <optgroup label='hide' style='display: none'>"
165 " <option value='one'>one</option>"
166 " </optgroup>"
167 " <option value='two'>two</option>"
168 " <option value='three'>three</option>"
169 " <option value='four'>four</option>"
170 " <option value='five'>five</option>"
171 "</select>";
172 // Load the test page.
173 LoadHTML(html.c_str());
174
175 // Set a minimum size and give focus so simulated events work.
176 view()->webwidget()->resize(blink::WebSize(500, 500));
177 view()->webwidget()->setFocus(true);
178 }
179
180};
181
182TEST_F(ExternalPopupMenuDisplayNoneTest, SelectItem) {
sudarshan.p9ff8ce32014-09-03 11:20:37183 IPC::TestSink& sink = render_thread_->sink();
184
[email protected]d0cd67482014-08-12 19:17:12185 // Click the text field once to show the popup.
186 EXPECT_TRUE(SimulateElementClick(kSelectID));
187
sudarshan.p9ff8ce32014-09-03 11:20:37188 // Read the message sent to browser to show the popup menu.
189 const IPC::Message* message =
190 sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
191 ASSERT_TRUE(message != NULL);
192 Tuple1<FrameHostMsg_ShowPopup_Params> param;
193 FrameHostMsg_ShowPopup::Read(message, &param);
194 // Number of items should match item count minus the number
195 // of "display: none" items.
196 ASSERT_EQ(5U, param.a.popup_items.size());
197
[email protected]d0cd67482014-08-12 19:17:12198 // Select index 1 item. This should select item with index 2,
199 // skipping the item with 'display: none'
avi485e5fd62014-08-25 23:26:14200 frame()->OnSelectPopupMenuItem(1);
[email protected]d0cd67482014-08-12 19:17:12201
avi485e5fd62014-08-25 23:26:14202 EXPECT_EQ(2, GetSelectedIndex());
[email protected]d0cd67482014-08-12 19:17:12203}
204
[email protected]e9ff79c2012-10-19 21:31:26205} // namespace content