1 | /* |
2 | * Copyright (C) 2017 Igalia S.L. |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2,1 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Library General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Library General Public License |
15 | * along with this library; see the file COPYING.LIB. If not, write to |
16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | * Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "config.h" |
21 | #include "WebViewTest.h" |
22 | |
23 | #include <wtf/RunLoop.h> |
24 | |
25 | class : public WebViewTest { |
26 | public: |
27 | MAKE_GLIB_TEST_FIXTURE(OptionMenuTest); |
28 | |
29 | () |
30 | { |
31 | g_signal_connect(m_webView, "show-option-menu" , G_CALLBACK(showOptionMenuCallback), this); |
32 | } |
33 | |
34 | () |
35 | { |
36 | g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); |
37 | if (m_menu) |
38 | close(); |
39 | } |
40 | |
41 | void () |
42 | { |
43 | if (!m_menu) |
44 | return; |
45 | |
46 | g_signal_handlers_disconnect_matched(m_menu.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); |
47 | m_menu = nullptr; |
48 | } |
49 | |
50 | static gboolean (WebKitWebView* webView, WebKitOptionMenu* , GdkEvent* event, GdkRectangle* rect, OptionMenuTest* test) |
51 | { |
52 | g_assert_true(test->m_webView == webView); |
53 | g_assert_nonnull(rect); |
54 | g_assert_true(WEBKIT_IS_OPTION_MENU(menu)); |
55 | test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(menu)); |
56 | test->showOptionMenu(menu, rect); |
57 | return TRUE; |
58 | } |
59 | |
60 | static void (WebKitOptionMenu* , OptionMenuTest* test) |
61 | { |
62 | g_assert_true(test->m_menu.get() == menu); |
63 | test->destroyMenu(); |
64 | } |
65 | |
66 | void (WebKitOptionMenu* , GdkRectangle* rect) |
67 | { |
68 | m_rectangle = *rect; |
69 | m_menu = menu; |
70 | g_signal_connect(m_menu.get(), "close" , G_CALLBACK(menuCloseCallback), this); |
71 | g_main_loop_quit(m_mainLoop); |
72 | } |
73 | |
74 | void clickAtPositionAndWaitUntilOptionMenuShown(int x, int y) |
75 | { |
76 | m_menu = nullptr; |
77 | RunLoop::main().dispatch([this, x, y] { clickMouseButton(x, y); }); |
78 | g_main_loop_run(m_mainLoop); |
79 | } |
80 | |
81 | void () |
82 | { |
83 | g_assert_nonnull(m_menu.get()); |
84 | webkit_option_menu_close(m_menu.get()); |
85 | g_assert_null(m_menu.get()); |
86 | } |
87 | |
88 | void (unsigned item) |
89 | { |
90 | g_assert_nonnull(m_menu.get()); |
91 | webkit_option_menu_activate_item(m_menu.get(), item); |
92 | g_assert_nonnull(m_menu.get()); |
93 | } |
94 | |
95 | void (unsigned item) |
96 | { |
97 | g_assert_nonnull(m_menu.get()); |
98 | webkit_option_menu_select_item(m_menu.get(), item); |
99 | g_assert_nonnull(m_menu.get()); |
100 | } |
101 | |
102 | GRefPtr<WebKitOptionMenu> ; |
103 | GdkRectangle ; |
104 | }; |
105 | |
106 | static void (OptionMenuTest* test, gconstpointer) |
107 | { |
108 | static const char html[] = |
109 | "<html><body>" |
110 | " <select style='position:absolute; left:1; top:10'>" |
111 | " <option title='The Foo Option'>Foo</option>" |
112 | " <option selected>Bar</option>" |
113 | " <option disabled>Baz</option>" |
114 | " </select></body></html>" ; |
115 | test->showInWindowAndWaitUntilMapped(); |
116 | test->loadHtml(html, nullptr); |
117 | test->waitUntilLoadFinished(); |
118 | |
119 | test->clickAtPositionAndWaitUntilOptionMenuShown(5, 15); |
120 | g_assert_true(WEBKIT_IS_OPTION_MENU(test->m_menu.get())); |
121 | g_assert_cmpint(webkit_option_menu_get_n_items(test->m_menu.get()), ==, 3); |
122 | auto* item = webkit_option_menu_get_item(test->m_menu.get(), 0); |
123 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Foo" ); |
124 | g_assert_cmpstr(webkit_option_menu_item_get_tooltip(item), ==, "The Foo Option" ); |
125 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
126 | g_assert_false(webkit_option_menu_item_is_group_child(item)); |
127 | g_assert_true(webkit_option_menu_item_is_enabled(item)); |
128 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
129 | item = webkit_option_menu_get_item(test->m_menu.get(), 1); |
130 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Bar" ); |
131 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
132 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
133 | g_assert_false(webkit_option_menu_item_is_group_child(item)); |
134 | g_assert_true(webkit_option_menu_item_is_enabled(item)); |
135 | g_assert_true(webkit_option_menu_item_is_selected(item)); |
136 | item = webkit_option_menu_get_item(test->m_menu.get(), 2); |
137 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Baz" ); |
138 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
139 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
140 | g_assert_false(webkit_option_menu_item_is_group_child(item)); |
141 | g_assert_false(webkit_option_menu_item_is_enabled(item)); |
142 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
143 | |
144 | test->close(); |
145 | g_assert_null(test->m_menu.get()); |
146 | } |
147 | |
148 | static void (OptionMenuTest* test, gconstpointer) |
149 | { |
150 | static const char html[] = |
151 | "<html><body>" |
152 | " <select style='position:absolute; left:1; top:10'>" |
153 | " <option>Root</option>" |
154 | " <optgroup label='Group 1'>" |
155 | " <option>Child 1-1</option>" |
156 | " <option disabled>Child 1-2</option>" |
157 | " </optgroup>" |
158 | " <optgroup label='Group 2'>" |
159 | " <option selected>Child 2-1</option>" |
160 | " <option>Child 2-2</option>" |
161 | " </optgroup>" |
162 | " <option>Tail</option>" |
163 | " </select></body></html>" ; |
164 | test->showInWindowAndWaitUntilMapped(); |
165 | test->loadHtml(html, nullptr); |
166 | test->waitUntilLoadFinished(); |
167 | |
168 | test->clickAtPositionAndWaitUntilOptionMenuShown(5, 15); |
169 | g_assert_true(WEBKIT_IS_OPTION_MENU(test->m_menu.get())); |
170 | g_assert_cmpint(webkit_option_menu_get_n_items(test->m_menu.get()), ==, 8); |
171 | auto* item = webkit_option_menu_get_item(test->m_menu.get(), 0); |
172 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Root" ); |
173 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
174 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
175 | g_assert_false(webkit_option_menu_item_is_group_child(item)); |
176 | g_assert_true(webkit_option_menu_item_is_enabled(item)); |
177 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
178 | item = webkit_option_menu_get_item(test->m_menu.get(), 1); |
179 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Group 1" ); |
180 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
181 | g_assert_true(webkit_option_menu_item_is_group_label(item)); |
182 | g_assert_false(webkit_option_menu_item_is_group_child(item)); |
183 | g_assert_false(webkit_option_menu_item_is_enabled(item)); |
184 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
185 | item = webkit_option_menu_get_item(test->m_menu.get(), 2); |
186 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Child 1-1" ); |
187 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
188 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
189 | g_assert_true(webkit_option_menu_item_is_group_child(item)); |
190 | g_assert_true(webkit_option_menu_item_is_enabled(item)); |
191 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
192 | item = webkit_option_menu_get_item(test->m_menu.get(), 3); |
193 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Child 1-2" ); |
194 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
195 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
196 | g_assert_true(webkit_option_menu_item_is_group_child(item)); |
197 | g_assert_false(webkit_option_menu_item_is_enabled(item)); |
198 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
199 | item = webkit_option_menu_get_item(test->m_menu.get(), 4); |
200 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Group 2" ); |
201 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
202 | g_assert_true(webkit_option_menu_item_is_group_label(item)); |
203 | g_assert_false(webkit_option_menu_item_is_group_child(item)); |
204 | g_assert_false(webkit_option_menu_item_is_enabled(item)); |
205 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
206 | item = webkit_option_menu_get_item(test->m_menu.get(), 5); |
207 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Child 2-1" ); |
208 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
209 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
210 | g_assert_true(webkit_option_menu_item_is_group_child(item)); |
211 | g_assert_true(webkit_option_menu_item_is_enabled(item)); |
212 | g_assert_true(webkit_option_menu_item_is_selected(item)); |
213 | item = webkit_option_menu_get_item(test->m_menu.get(), 6); |
214 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Child 2-2" ); |
215 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
216 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
217 | g_assert_true(webkit_option_menu_item_is_group_child(item)); |
218 | g_assert_true(webkit_option_menu_item_is_enabled(item)); |
219 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
220 | item = webkit_option_menu_get_item(test->m_menu.get(), 7); |
221 | g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Tail" ); |
222 | g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
223 | g_assert_false(webkit_option_menu_item_is_group_label(item)); |
224 | g_assert_false(webkit_option_menu_item_is_group_child(item)); |
225 | g_assert_true(webkit_option_menu_item_is_enabled(item)); |
226 | g_assert_false(webkit_option_menu_item_is_selected(item)); |
227 | } |
228 | |
229 | static void (OptionMenuTest* test, gconstpointer) |
230 | { |
231 | static const char html[] = |
232 | "<html><body>" |
233 | " <select id='combo' style='position:absolute; left:1; top:10'>" |
234 | " <option>Foo</option>" |
235 | " <option>Bar</option>" |
236 | " <option>Baz</option>" |
237 | " </select></body></html>" ; |
238 | test->showInWindowAndWaitUntilMapped(); |
239 | test->loadHtml(html, nullptr); |
240 | test->waitUntilLoadFinished(); |
241 | |
242 | test->clickAtPositionAndWaitUntilOptionMenuShown(5, 15); |
243 | g_assert_true(WEBKIT_IS_OPTION_MENU(test->m_menu.get())); |
244 | g_assert_cmpint(webkit_option_menu_get_n_items(test->m_menu.get()), ==, 3); |
245 | test->activateItem(1); |
246 | auto* result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex" , nullptr); |
247 | g_assert_nonnull(result); |
248 | g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 1); |
249 | |
250 | // We should close the menu after activate, further activates will be ignored. |
251 | test->activateItem(2); |
252 | result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex" , nullptr); |
253 | g_assert_nonnull(result); |
254 | g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 1); |
255 | |
256 | test->close(); |
257 | } |
258 | |
259 | static void (OptionMenuTest* test, gconstpointer) |
260 | { |
261 | static const char html[] = |
262 | "<html><body>" |
263 | " <select id='combo' style='position:absolute; left:1; top:10'>" |
264 | " <option>Foo</option>" |
265 | " <option>Bar</option>" |
266 | " <option>Baz</option>" |
267 | " </select></body></html>" ; |
268 | test->showInWindowAndWaitUntilMapped(); |
269 | test->loadHtml(html, nullptr); |
270 | test->waitUntilLoadFinished(); |
271 | |
272 | test->clickAtPositionAndWaitUntilOptionMenuShown(5, 15); |
273 | g_assert_true(WEBKIT_IS_OPTION_MENU(test->m_menu.get())); |
274 | g_assert_cmpint(webkit_option_menu_get_n_items(test->m_menu.get()), ==, 3); |
275 | |
276 | // Select item changes the combo text, but not the currently selected item. |
277 | test->selectItem(2); |
278 | auto* result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex" , nullptr); |
279 | g_assert_nonnull(result); |
280 | g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 0); |
281 | |
282 | // It can be called multiple times. |
283 | test->selectItem(1); |
284 | result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex" , nullptr); |
285 | g_assert_nonnull(result); |
286 | g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 0); |
287 | |
288 | // And closing the menu activates the currently selected item. |
289 | test->close(); |
290 | result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex" , nullptr); |
291 | g_assert_nonnull(result); |
292 | g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 1); |
293 | } |
294 | |
295 | void beforeAll() |
296 | { |
297 | OptionMenuTest::add("WebKitWebView" , "option-menu-simple" , testOptionMenuSimple); |
298 | OptionMenuTest::add("WebKitWebView" , "option-menu-groups" , testOptionMenuGroups); |
299 | OptionMenuTest::add("WebKitWebView" , "option-menu-activate" , testOptionMenuActivate); |
300 | OptionMenuTest::add("WebKitWebView" , "option-menu-select" , testOptionMenuSelect); |
301 | } |
302 | |
303 | void afterAll() |
304 | { |
305 | } |
306 | |